package com.panfeng.xcloud.scheduler.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.ki5fpl.tronj.abi.datatypes.Bool;
import com.panfeng.xcloud.boss.provider.dto.request.PinBarCandlerStickDetailDTO;
import com.panfeng.xcloud.boss.provider.dto.request.QuantBotDetailDTO;
import com.panfeng.xcloud.common.core.candle.Entry;
import com.panfeng.xcloud.common.core.candle.MyCandleEntry;
import com.panfeng.xcloud.common.core.enums.MovingAveragePeriodEnum;
import com.panfeng.xcloud.common.core.enums.SystemInnerTypeEnum;
import com.panfeng.xcloud.common.core.utils.FinanceIndicatorsUtil;
import com.panfeng.xcloud.scheduler.constants.SystemParamContants;
import com.panfeng.xcloud.scheduler.dto.SlowStochRsiResult;
import com.panfeng.xcloud.scheduler.dto.SupertrendResult;
import com.panfeng.xcloud.scheduler.service.ICalculatePriceService;
import com.panfeng.xcloud.scheduler.service.IFeignService;
import com.panfeng.xcloud.scheduler.service.ITechniqueSymbolService4BackTest;
import com.panfeng.xcloud.scheduler.util.TrendLines;
import groovy.util.logging.Slf4j;
import org.apache.commons.math3.stat.regression.SimpleRegression;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.ta4j.core.*;
import org.ta4j.core.indicators.*;
import org.ta4j.core.indicators.adx.ADXIndicator;
import org.ta4j.core.indicators.adx.MinusDIIndicator;
import org.ta4j.core.indicators.adx.PlusDIIndicator;
import org.ta4j.core.indicators.helpers.*;
import org.ta4j.core.indicators.volume.OnBalanceVolumeIndicator;
import org.ta4j.core.num.Num;
import org.ta4j.core.num.PrecisionNum;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * 风险控制类
 */
@Slf4j
@Service
public class TechniqueSymbolServiceImpl4BackTest implements ITechniqueSymbolService4BackTest {

    @Autowired
    private ICalculatePriceService iCalculatePriceService;

    private static Logger log = LoggerFactory.getLogger(TechniqueSymbolServiceImpl4BackTest.class);

    @Autowired
    private IFeignService feignService;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 获取某根蜡烛
     */
    public List<MyCandleEntry> getCandlerStick(JSONObject candleStick) throws Exception {
        JSONArray candlesticks = candleStick.getJSONArray("candlesticks");
        List<MyCandleEntry> candleEntries = new ArrayList<>();
        for (int i = 0; i < candlesticks.size(); i++) {
            JSONObject obj = (JSONObject) (candlesticks.get(i));
            MyCandleEntry candleEntry = new MyCandleEntry(i, obj.getFloatValue("high"), obj.getFloatValue("low"), obj.getFloatValue("open"), obj.getFloatValue("close"), obj.getFloatValue("volume"), obj.getLongValue("openTime"), obj.getLongValue("closeTime"), obj.getBigDecimal("quoteAssetVolume"));
            candleEntries.add(candleEntry);
        }

        return candleEntries;
    }

    /**
     * 获取某段时间内最高价格和那根ATR
     */
    public BigDecimal[] getHighestPriceAndAtr(List<Num> atrs, List<MyCandleEntry> candleEntries, int index, int period) throws Exception {
        BigDecimal highestPrice = new BigDecimal(candleEntries.get(index).getClose());
        int chooseIndex = 0;

        for (int i = 0; i < period; i++) {
            MyCandleEntry candleEntry = candleEntries.get(index - i);
            BigDecimal tempPrice = new BigDecimal(candleEntry.getHigh());
            Boolean judge = tempPrice.compareTo(highestPrice) > 0;
            highestPrice = judge ? tempPrice : highestPrice;
            chooseIndex = judge ? i : chooseIndex;
        }
        BigDecimal chooseAtr = new BigDecimal(atrs.get(atrs.size() - 2 - chooseIndex).floatValue());

        BigDecimal[] results = new BigDecimal[2];
        results[0] = highestPrice;
        results[1] = chooseAtr;
        return results;
    }

    public BigDecimal getHighestPrice(List<MyCandleEntry> candleEntries, int index, int period) throws Exception {
        BigDecimal highestPrice = new BigDecimal(candleEntries.get(index).getClose());

        for (int i = 0; i < period; i++) {
            MyCandleEntry candleEntry = candleEntries.get(index - i);
            BigDecimal tempPrice = new BigDecimal(candleEntry.getHigh());
            Boolean judge = tempPrice.compareTo(highestPrice) > 0;
            highestPrice = judge ? tempPrice : highestPrice;
        }

        return highestPrice;
    }

    /**
     * 获取某段时间内最低价格和那根ATR
     */
    public BigDecimal[] getLowestPriceAndAtr(List<Num> atrs, List<MyCandleEntry> candleEntries, int index, int period) throws Exception {
        BigDecimal lowestPrice = new BigDecimal(candleEntries.get(index).getClose());
        int chooseIndex = 0;

        for (int i = 0; i < period; i++) {
            MyCandleEntry candleEntry = candleEntries.get(index - i);
            BigDecimal tempPrice = new BigDecimal(candleEntry.getLow());
            Boolean judge = tempPrice.compareTo(lowestPrice) < 0;
            lowestPrice = judge ? tempPrice : lowestPrice;
            chooseIndex = judge ? i : chooseIndex;
        }
        BigDecimal chooseAtr = new BigDecimal(atrs.get(atrs.size() - 2 - chooseIndex).floatValue());

        BigDecimal[] results = new BigDecimal[2];
        results[0] = lowestPrice;
        results[1] = chooseAtr;
        return results;
    }

    public BigDecimal getLowestPrice(List<MyCandleEntry> candleEntries, int index, int period) throws Exception {
        BigDecimal lowestPrice = new BigDecimal(candleEntries.get(index).getClose());

        for (int i = 0; i < period; i++) {
            MyCandleEntry candleEntry = candleEntries.get(index - i);
            BigDecimal tempPrice = new BigDecimal(candleEntry.getLow());
            Boolean judge = tempPrice.compareTo(lowestPrice) < 0;
            lowestPrice = judge ? tempPrice : lowestPrice;
        }

        return lowestPrice;
    }

    /**
     * 开多趋势中突破判断
     */
    public QuantBotDetailDTO[] judgeTrendBuyBreakThroughOpen(JSONObject candleStick, int atrPeriod, QuantBotDetailDTO quantBotDetailDTO, BarSeries barSeries, String destinationCoins, BigDecimal slippage) throws Exception {
        List<MyCandleEntry> candleEntries = getCandlerStick(candleStick);
        List<Num> atrs = getATR(barSeries, atrPeriod);
        MyCandleEntry nowCandleEntry5m = candleEntries.get(candleEntries.size() - 1);
        MyCandleEntry lastCandleEntry5m = candleEntries.get(candleEntries.size() - 2);
        MyCandleEntry last2CandleEntry5m = candleEntries.get(candleEntries.size() - 3);

        List<Entry> emas200 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA200);
        List<Entry> emas120 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA120);
        List<Entry> emas90 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA90);
        List<Entry> emas60 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA60);
        List<Entry> emas30 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA30);
        List<Entry> emas10 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA10);
        List<Entry> emas5 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA5);
        BigDecimal lastEmaValue120 = new BigDecimal((emas120.get(emas120.size() - 2)).getY());
        BigDecimal lastEmaValue90 = new BigDecimal((emas90.get(emas90.size() - 2)).getY());
        BigDecimal lastEmaValue60 = new BigDecimal((emas60.get(emas60.size() - 2)).getY());
        BigDecimal lastEmaValue30 = new BigDecimal((emas30.get(emas30.size() - 2)).getY());
        BigDecimal last2EmaValue30 = new BigDecimal((emas30.get(emas30.size() - 3)).getY());
        BigDecimal lastEmaValue200 = new BigDecimal((emas200.get(emas200.size() - 2)).getY());
        BigDecimal lastEmaValue10 = new BigDecimal((emas10.get(emas10.size() - 2)).getY());
        BigDecimal last2EmaValue10 = new BigDecimal((emas10.get(emas10.size() - 3)).getY());
        BigDecimal lastEmaValue5 = new BigDecimal((emas5.get(emas5.size() - 2)).getY());
        BigDecimal nowAtr = new BigDecimal(atrs.get(atrs.size() - 1).floatValue());
        BigDecimal lastAtr = new BigDecimal(atrs.get(atrs.size() - 2).floatValue());
        BigDecimal last2Atr = new BigDecimal(atrs.get(atrs.size() - 3).floatValue());
        /*if (!quantBotDetailDTO.getCanOpen()) {
            if (new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue10) > 0) {
                quantBotDetailDTO.setCanOpen(true);
                quantBotDetailDTO.setMultipleAtr(new BigDecimal("0"));
            }
        }*/

        /*int diBarCount = 14;
        int adxBarCount = 14;
        double lastAdx = getADX(barSeries, diBarCount, adxBarCount, barSeries.getEndIndex() - 1);*/

        int rsiTimeFrame = 14;
        BigDecimal lastRsi = getRsi(barSeries, rsiTimeFrame, barSeries.getEndIndex() - 1);
        BigDecimal last2Rsi = getRsi(barSeries, rsiTimeFrame, barSeries.getEndIndex() - 2);
        BigDecimal atrSlip = lastAtr.multiply(new BigDecimal("3"));

        BigDecimal[] highestAndAtr = getHighestPriceAndAtr(atrs, candleEntries, candleEntries.size() - 3, 20);
        BigDecimal highestPrice = highestAndAtr[0];
        BigDecimal highestAtr = highestAndAtr[1];

        if (/*new BigDecimal(last2CandleEntry5m.getClose()).compareTo(lastEmaValue10.add(atrSlip)) < 0
                &&*/ /*new BigDecimal(lastCandleEntry5m.getOpen()).compareTo(lastEmaValue200) > 0
                && new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue200) < 0*/
                /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue200) >= 0 &&
                        new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue120) >= 0 &&
                        new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue60) >= 0 &&
                        new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue10) >= 0*/
            /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue60) > 0 &&*/
                new BigDecimal(lastCandleEntry5m.getClose()).compareTo(highestPrice) > 0
            /*lastRsi.doubleValue() >= 40 && last2Rsi.doubleValue() < 40*/
            /*lastRsi.doubleValue() < 30*/

            /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lowestPrice) < 0*/
                /*lastRsi.doubleValue() >= 30 && last2Rsi.doubleValue() < 30
                        && new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue120) > 0*/

            /*&& new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue30) < 0*/
            /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(new BigDecimal(lastCandleEntry5m.getOpen())) < 0*/
                /*&& lastRsi.compareTo(new BigDecimal("10")) >= 0
                && last2Rsi.compareTo(new BigDecimal("10")) < 0*/
            /*&& lastEmaValue10.compareTo(lastEmaValue60) > 0*/
            /*&& new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue20) < 0*/
            /*&& lastRsi.doubleValue() < 10*/
            /*&& quantBotDetailDTO.getCanOpen()*/
        ) {
            /*BigDecimal atrSlipRatio = atrSlip.divide(new BigDecimal(lastCandleEntry5m.getClose()), 6, BigDecimal.ROUND_DOWN);
            System.out.println("开多偏离率:" + atrSlipRatio);*/
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
            String progressTime = barSeries.getBar(barSeries.getEndIndex()).getBeginTime().format(formatter);
            BigDecimal nowOpen = new BigDecimal(nowCandleEntry5m.getOpen());
            BigDecimal[] lowestAndAtr = getLowestPriceAndAtr(atrs, candleEntries, candleEntries.size() - 2, 20);
            BigDecimal lowestPrice = lowestAndAtr[0];
            BigDecimal lowestAtr = lowestAndAtr[1];
            BigDecimal initStopLossPrice = lowestPrice.subtract(lowestAtr.multiply(new BigDecimal("0")));
            BigDecimal initStopLossRate = nowOpen.subtract(initStopLossPrice).divide(nowOpen, 6, BigDecimal.ROUND_DOWN).abs();
            /*BigDecimal temp = new BigDecimal("0.05");
            BigDecimal initStopLossPrice = (BigDecimal.ONE.subtract(temp)).multiply(nowOpen);
            BigDecimal initStopLossRate = nowOpen.subtract(initStopLossPrice).divide(nowOpen, 6, BigDecimal.ROUND_DOWN).abs();*/
            /*BigDecimal[] highestPriceAndAtr = getHighestPriceAndAtr(atrs, candleEntries, candleEntries.size() - 2, 1);
            BigDecimal highestPrice = highestPriceAndAtr[0];
            BigDecimal highestAtr = highestPriceAndAtr[1];
            BigDecimal initStopLossPrice = highestPrice.add(highestAtr.multiply(new BigDecimal("0")));
            BigDecimal initStopLossRate = initStopLossPrice.subtract(nowOpen).divide(nowOpen, 6, BigDecimal.ROUND_DOWN).abs();*/

            BigDecimal limitRate = nowOpen.subtract(initStopLossPrice).divide(nowOpen, 6, BigDecimal.ROUND_DOWN).abs();
            if (initStopLossRate.compareTo(SystemParamContants.stop_loss_max) > 0) {
                return new QuantBotDetailDTO[]{quantBotDetailDTO, null};
            }

            BigDecimal initStopMax = (BigDecimal) redisTemplate.opsForValue().get("initStopMax:" + destinationCoins);
            List<BigDecimal> initStopMaxList = (List<BigDecimal>) redisTemplate.opsForValue().get("initStopMaxList:" + destinationCoins);
            if (initStopLossRate.compareTo(initStopMax) > 0) {
                initStopMax = initStopLossRate;
                initStopMaxList.add(initStopMax);
            }
            redisTemplate.opsForValue().set("initStopMax:" + destinationCoins, initStopMax);
            redisTemplate.opsForValue().set("initStopMaxList:" + destinationCoins, initStopMaxList);

            BigDecimal stopLossRate = initStopLossRate.negate();
            BigDecimal stopWinRatio = initStopLossRate.multiply(new BigDecimal("1"));
            //BigDecimal stopWinRatio = new BigDecimal("0.005");
            //BigDecimal breakEvenRate = stopWinRatio;
            BigDecimal breakEvenRate = new BigDecimal("0.01");
            //BigDecimal breakEvenRate = stopLossRate.negate();

            PinBarCandlerStickDetailDTO pinBarCandlerStickDetailDTO = new PinBarCandlerStickDetailDTO();
            pinBarCandlerStickDetailDTO.setInitStopLossPrice(initStopLossPrice);
            pinBarCandlerStickDetailDTO.setStopLossPrice(initStopLossPrice);
            pinBarCandlerStickDetailDTO.setStopWinRate(stopWinRatio);
            pinBarCandlerStickDetailDTO.setBreakEvenRate(breakEvenRate);
            pinBarCandlerStickDetailDTO.setStopLossRate(stopLossRate);
            pinBarCandlerStickDetailDTO.setOpen(nowOpen.multiply(BigDecimal.ONE.add(slippage)));
            quantBotDetailDTO.setCurrentAddTime(String.valueOf(nowCandleEntry5m.getOpenTime()));
            //给移动止盈获取上次breakEventRate数据使用
            quantBotDetailDTO.setLastTimeRise(String.valueOf(pinBarCandlerStickDetailDTO.getBreakEvenRate()));

            quantBotDetailDTO.setPinBarCandlerStickDetailDTO(pinBarCandlerStickDetailDTO);

            System.out.println(quantBotDetailDTO.getDestinationCoin() + " 多单开仓进度时间: " + progressTime + ",最大初始止损率:" + initStopMax + ",开单均价:" + pinBarCandlerStickDetailDTO.getOpen().setScale(6, RoundingMode.HALF_UP));

            return new QuantBotDetailDTO[]{quantBotDetailDTO, quantBotDetailDTO};
        } else {
            return new QuantBotDetailDTO[]{quantBotDetailDTO, null};
        }
    }

    public QuantBotDetailDTO[] judgeTrendBuyBreakThroughOpen2(JSONObject candleStick, int atrPeriod, QuantBotDetailDTO quantBotDetailDTO, BarSeries barSeries, String destinationCoins, BigDecimal slippage) throws Exception {
        int shortPeriod = 12;
        int longPeriod = 26;
        int signalPeriod = 9;
        int judgePeriod = 1;
        int judgeRiseSpacePeriod = 20;

        List<MyCandleEntry> candleEntries = getCandlerStick(candleStick);
        List<Num> atrs = getATR(barSeries, atrPeriod);
        MyCandleEntry nowCandleEntry5m = candleEntries.get(candleEntries.size() - 1);
        MyCandleEntry lastCandleEntry5m = candleEntries.get(candleEntries.size() - 2);
        MyCandleEntry last2CandleEntry5m = candleEntries.get(candleEntries.size() - 3);
        MyCandleEntry last3CandleEntry5m = candleEntries.get(candleEntries.size() - 4);
        MyCandleEntry last4CandleEntry5m = candleEntries.get(candleEntries.size() - 5);
        MyCandleEntry last5CandleEntry5m = candleEntries.get(candleEntries.size() - 6);
        MyCandleEntry last6CandleEntry5m = candleEntries.get(candleEntries.size() - 7);
        MyCandleEntry last7CandleEntry5m = candleEntries.get(candleEntries.size() - 8);
        MyCandleEntry last8CandleEntry5m = candleEntries.get(candleEntries.size() - 9);

        List<Entry> emas200 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA200);
        List<Entry> emas120 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA120);
        List<Entry> emas90 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA90);
        List<Entry> emas60 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA60);
        List<Entry> emas20 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA20);
        List<Entry> emas10 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA10);
        List<Entry> emas5 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA5);
        BigDecimal lastEmaValue120 = new BigDecimal((emas120.get(emas120.size() - 2)).getY());
        BigDecimal last2EmaValue120 = new BigDecimal((emas120.get(emas120.size() - 3)).getY());
        BigDecimal lastEmaValue90 = new BigDecimal((emas90.get(emas90.size() - 2)).getY());
        BigDecimal last2EmaValue90 = new BigDecimal((emas90.get(emas90.size() - 3)).getY());
        BigDecimal lastEmaValue60 = new BigDecimal((emas60.get(emas60.size() - 2)).getY());
        BigDecimal lastEmaValue20 = new BigDecimal((emas20.get(emas20.size() - 2)).getY());
        BigDecimal lastEmaValue200 = new BigDecimal((emas200.get(emas200.size() - 2)).getY());
        BigDecimal lastEmaValue10 = new BigDecimal((emas10.get(emas10.size() - 2)).getY());
        BigDecimal lastEmaValue5 = new BigDecimal((emas5.get(emas5.size() - 2)).getY());

        float[] mas120 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA120);
        float[] mas60 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA60);
        float[] mas20 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA20);
        BigDecimal lastMaValue120 = new BigDecimal(mas120[1]);
        BigDecimal lastMaValue60 = new BigDecimal(mas60[1]);
        BigDecimal lastMaValue20 = new BigDecimal(mas20[1]);
        /*Boolean judgeEma200 = true;
        for (int i = 0; i < judgePeriod; i++) {
            MyCandleEntry chooseCandleEntry5m = candleEntries.get(candleEntries.size() - 2 - i);
            BigDecimal open = new BigDecimal(chooseCandleEntry5m.getOpen());
            BigDecimal close = new BigDecimal(chooseCandleEntry5m.getClose());
            BigDecimal min = open.compareTo(close) > 0 ? close : open;
            BigDecimal chooseEmaValue200 = new BigDecimal((emas200.get(emas200.size() - 2 - i)).getY());
            //BigDecimal chooseAtr = new BigDecimal(atrs.get(atrs.size() - 2 - i).floatValue()).multiply(new BigDecimal("1.5"));
            if (min.compareTo(chooseEmaValue200) < 0) {
                judgeEma200 = false;
                break;
            }
        }*/

        List<Num>[] macd_signal_value = getMACD_signal_value(barSeries, shortPeriod, longPeriod, signalPeriod);
        List<Num> macdvalues = macd_signal_value[0];
        /*List<Num> signalvalues = macd_signal_value[1];

        double macdLast = macdvalues.get(candleEntries.size() - 2 - signalPeriod).doubleValue();
        double macdLast2 = macdvalues.get(candleEntries.size() - 3 - signalPeriod).doubleValue();

        double signalLast = signalvalues.get(candleEntries.size() - 2 - signalPeriod).doubleValue();
        double signalLast2 = signalvalues.get(candleEntries.size() - 3 - signalPeriod).doubleValue();

        BigDecimal atrLast = new BigDecimal(atrs.get(atrs.size() - 2).floatValue());
        BigDecimal atrLast2 = new BigDecimal(atrs.get(atrs.size() - 3).floatValue());
        BigDecimal atrLast3 = new BigDecimal(atrs.get(atrs.size() - 4).floatValue());
        Boolean judgeAtr = atrLast.subtract(atrLast2).divide(atrLast2, 6, BigDecimal.ROUND_DOWN).compareTo(new BigDecimal("0.1")) < 0;
        Boolean judgeAtr2 = atrLast2.subtract(atrLast3).divide(atrLast3, 6, BigDecimal.ROUND_DOWN).compareTo(new BigDecimal("0.1")) < 0;
*/
        //boolean isBullEntry = isBullEntry(candleEntries, macdvalues, signalPeriod, judgePeriod);

        /*Boolean judge = (lastCandleEntry5m.getClose() > lastCandleEntry5m.getOpen()) &&
                (last2CandleEntry5m.getClose() < last2CandleEntry5m.getOpen()) &&
                (lastCandleEntry5m.getClose() > last2CandleEntry5m.getOpen());*/

        /*BigDecimal subtract1 = new BigDecimal(lastCandleEntry5m.getOpen()).subtract(new BigDecimal(lastCandleEntry5m.getLow()));
        BigDecimal subtract2 = new BigDecimal(lastCandleEntry5m.getHigh()).subtract(new BigDecimal(lastCandleEntry5m.getLow()));
        if (subtract2.compareTo(BigDecimal.ZERO) == 0) {
            return null;
        }
        Boolean judge2 = (subtract1.divide(subtract2, 6, BigDecimal.ROUND_DOWN)).compareTo(new BigDecimal("0.6")) > 0;
        Boolean judge3 = new BigDecimal(lastCandleEntry5m.getClose()).compareTo(new BigDecimal(lastCandleEntry5m.getOpen())) > 0;*/
        /*List<Entry> emas13 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA13);
        List<Entry> emas21 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA21);
        List<Entry> emas55 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA55);
        BigDecimal lastEmaValue13 = new BigDecimal((emas13.get(emas13.size() - 2)).getY());
        BigDecimal lastEmaValue21 = new BigDecimal((emas21.get(emas21.size() - 2)).getY());
        BigDecimal lastEmaValue55 = new BigDecimal((emas55.get(emas55.size() - 2)).getY());
        BigDecimal last2EmaValue13 = new BigDecimal((emas13.get(emas13.size() - 3)).getY());
        BigDecimal last2EmaValue21 = new BigDecimal((emas21.get(emas21.size() - 3)).getY());
        BigDecimal last2EmaValue55 = new BigDecimal((emas55.get(emas55.size() - 3)).getY());
        Boolean judge4 = lastEmaValue21.compareTo(lastEmaValue55) > 0 &&
                last2EmaValue21.compareTo(last2EmaValue55) < 0 &&
                lastEmaValue13.compareTo(lastEmaValue21) > 0;*/

        /*float last2Body = last2CandleEntry5m.getClose() - last2CandleEntry5m.getOpen();
        float last3Body = last3CandleEntry5m.getClose() - last3CandleEntry5m.getOpen();
        float last4Body = last4CandleEntry5m.getClose() - last4CandleEntry5m.getOpen();
        Boolean judge2 = (last2Body < 0) && (last3Body < 0) && (last4Body < 0);
        Boolean judge5 = new BigDecimal(last2CandleEntry5m.getClose()).compareTo(new BigDecimal(last2CandleEntry5m.getOpen())) < 0 &&
                new BigDecimal(lastCandleEntry5m.getClose()).compareTo(new BigDecimal(lastCandleEntry5m.getOpen())) > 0;
        Boolean judge6 = new BigDecimal(last2CandleEntry5m.getClose()).compareTo(new BigDecimal(lastCandleEntry5m.getOpen())) > 0 &&
                new BigDecimal(last2CandleEntry5m.getOpen()).compareTo(new BigDecimal(lastCandleEntry5m.getClose())) < 0;
        Boolean judgeStar = checkStar(lastCandleEntry5m.getClose(), lastCandleEntry5m.getOpen(),
                lastCandleEntry5m.getHigh(), lastCandleEntry5m.getLow());*/
        /*int rsiTimeFrame21 = 21;
        BigDecimal lastRsi21 = getRsi(barSeries, rsiTimeFrame21, barSeries.getEndIndex() - 1);
        BigDecimal last2Rsi21 = getRsi(barSeries, rsiTimeFrame21, barSeries.getEndIndex() - 2);

        int rsiTimeFrame55 = 55;
        BigDecimal lastRsi55 = getRsi(barSeries, rsiTimeFrame55, barSeries.getEndIndex() - 1);
        BigDecimal last2Rsi55 = getRsi(barSeries, rsiTimeFrame55, barSeries.getEndIndex() - 2);

        Boolean judgeRsi = lastRsi21.compareTo(lastRsi55) > 0 && last2Rsi21.compareTo(last2Rsi55) < 0;*/
        /*double macdLast3 = macdvalues.get(candleEntries.size() - 4 - signalPeriod).doubleValue();
        double macdLast4 = macdvalues.get(candleEntries.size() - 5 - signalPeriod).doubleValue();
        double[] macdValues = {macdLast4, macdLast3, macdLast2, macdLast};*/

        //1.（上一根K线最高价-取30根前的K线最高价）/取30根前的K线最高价 < 0
        /*MyCandleEntry last30CandleEntry5m = candleEntries.get(candleEntries.size() - 31);
        Boolean judgeA = new BigDecimal(lastCandleEntry5m.getHigh()).subtract(new BigDecimal(last30CandleEntry5m.getHigh())).
                divide(new BigDecimal(last30CandleEntry5m.getHigh()), 6, BigDecimal.ROUND_DOWN).compareTo(new BigDecimal("0")) < 0;
        //2.（上根RSI - 上上根RSI）/上上根RSI > 0
        int rsiTimeFrame = 14;
        BigDecimal lastRsi = getRsi(barSeries, rsiTimeFrame, barSeries.getEndIndex() - 1);
        BigDecimal last2Rsi = getRsi(barSeries, rsiTimeFrame, barSeries.getEndIndex() - 2);
        Boolean judgeB = lastRsi.subtract(last2Rsi).divide(last2Rsi, 6, BigDecimal.ROUND_DOWN).compareTo(new BigDecimal("0")) > 0;
        //3.上根RSI < 55
        Boolean judgeC = lastRsi.compareTo(new BigDecimal("55")) < 0;*/

        int diBarCount = 14;
        int adxBarCount = 14;
        double lastAdx = getADX(barSeries, diBarCount, adxBarCount, barSeries.getEndIndex() - 1);
        double last2Adx = getADX(barSeries, diBarCount, adxBarCount, barSeries.getEndIndex() - 2);
        /*double last2Adx = getADX(barSeries, diBarCount, adxBarCount, barSeries.getEndIndex() - 2);
        double lastPlusDI = getPlusDI(barSeries, diBarCount, barSeries.getEndIndex() - 1);
        double lastMinusDI = getMinusDI(barSeries, diBarCount, barSeries.getEndIndex() - 1);*/
        //double last2PlusDI = getPlusDI(barSeries, diBarCount, barSeries.getEndIndex() - 2);
        //double last2MinusDI = getMinusDI(barSeries, diBarCount, barSeries.getEndIndex() - 2);
        /*float factor = 3f;
        int superTrendAtrPeriod = 10;
        SupertrendResult lastSupertrendResult = calculateSupertrend(barSeries, factor, superTrendAtrPeriod, barSeries.getEndIndex() - 1);*/
        //SupertrendResult last2SupertrendResult = calculateSupertrend(barSeries, factor, superTrendAtrPeriod, barSeries.getEndIndex() - 2);
        //SupertrendResult last3SupertrendResult = calculateSupertrend(barSeries, factor, superTrendAtrPeriod, barSeries.getEndIndex() - 3);

        /*int cciPeriod = 20;
        double lastCci = getCCI(barSeries, cciPeriod, barSeries.getEndIndex() - 1);
        double last2Cci = getCCI(barSeries, cciPeriod, barSeries.getEndIndex() - 2);
        double last3Cci = getCCI(barSeries, cciPeriod, barSeries.getEndIndex() - 3);*/

        int rsiBarCount = 14;
        int stockBarCount = 14;
        int kPeriod = 6;
        int dPeriod = 6;
        Num[] lastStochRsi = getStochRsi(barSeries, rsiBarCount, stockBarCount, kPeriod, dPeriod, barSeries.getEndIndex() - 1);
        Num[] last2StochRsi = getStochRsi(barSeries, rsiBarCount, stockBarCount, kPeriod, dPeriod, barSeries.getEndIndex() - 2);
        Num lastStochK = lastStochRsi[0];
        Num lastStochD = lastStochRsi[1];
        Num last2StochK = last2StochRsi[0];
        Num last2StochD = last2StochRsi[1];

        /*int length = 10;
        int smoothK = 6;
        int smoothD = 3;
        SlowStochRsiResult lastSlowStochRsi = getSlowStochRsi(barSeries, length, smoothK, smoothD, barSeries.getEndIndex() - 1);*/

        /*int rsiTimeFrame = 14;
        BigDecimal lastRsi = getRsi(barSeries, rsiTimeFrame, barSeries.getEndIndex() - 1);*/

        /*double lastOBV = getOBV(barSeries, barSeries.getEndIndex() - 1);
        double last2OBV = getOBV(barSeries, barSeries.getEndIndex() - 2);*/

        /*List<Entry> emas3 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA3);
        BigDecimal lastEmaValue3 = new BigDecimal((emas3.get(emas3.size() - 2)).getY());
        BigDecimal last2EmaValue3 = new BigDecimal((emas3.get(emas3.size() - 3)).getY());
        BigDecimal degreeEma3 = FinanceIndicatorsUtil.getMaDegree(lastEmaValue3, last2EmaValue3);

        List<Entry> emas6 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA6);
        BigDecimal lastEmaValue6 = new BigDecimal((emas6.get(emas6.size() - 2)).getY());
        BigDecimal last2EmaValue6 = new BigDecimal((emas6.get(emas6.size() - 3)).getY());
        BigDecimal degreeEma6 = FinanceIndicatorsUtil.getMaDegree(lastEmaValue6, last2EmaValue6);

        List<Entry> emas9 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA9);
        BigDecimal lastEmaValue9 = new BigDecimal((emas9.get(emas9.size() - 2)).getY());
        BigDecimal last2EmaValue9 = new BigDecimal((emas9.get(emas9.size() - 3)).getY());
        BigDecimal degreeEma9 = FinanceIndicatorsUtil.getMaDegree(lastEmaValue9, last2EmaValue9);

        List<Entry> emas12 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA12);
        BigDecimal lastEmaValue12 = new BigDecimal((emas12.get(emas12.size() - 2)).getY());
        BigDecimal last2EmaValue12 = new BigDecimal((emas12.get(emas12.size() - 3)).getY());
        BigDecimal degreeEma12 = FinanceIndicatorsUtil.getMaDegree(lastEmaValue12, last2EmaValue12);

        List<Entry> emas20 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA20);
        BigDecimal lastEmaValue20 = new BigDecimal((emas20.get(emas20.size() - 2)).getY());
        BigDecimal last2EmaValue20 = new BigDecimal((emas20.get(emas20.size() - 3)).getY());
        BigDecimal degreeEma20 = FinanceIndicatorsUtil.getMaDegree(lastEmaValue20, last2EmaValue20);

        Boolean judgeEmaDegree = degreeEma3.compareTo(BigDecimal.ZERO) > 0 && degreeEma6.compareTo(BigDecimal.ZERO) > 0 &&
                degreeEma9.compareTo(BigDecimal.ZERO) > 0 && degreeEma12.compareTo(BigDecimal.ZERO) > 0 && degreeEma20.compareTo(BigDecimal.ZERO) > 0;*/

        /*float last2JudgePrice = last2CandleEntry5m.getClose() > last2CandleEntry5m.getOpen() ? last2CandleEntry5m.getClose() : last2CandleEntry5m.getOpen();
        float lastJudgePrice = lastCandleEntry5m.getClose();*/

        //上根蜡烛收盘价-上根蜡烛开盘价
        BigDecimal subtract2 = new BigDecimal(lastCandleEntry5m.getClose()).subtract(new BigDecimal(lastCandleEntry5m.getOpen()));
        //上根蜡烛开盘价-上根蜡烛最低点
        BigDecimal subtract3 = new BigDecimal(lastCandleEntry5m.getOpen()).subtract(new BigDecimal(lastCandleEntry5m.getLow()));
        //上根蜡烛最高点-上根蜡烛最低点
        BigDecimal subtract4 = new BigDecimal(lastCandleEntry5m.getHigh()).subtract(new BigDecimal(lastCandleEntry5m.getLow()));
//
//        //上根蜡烛图实体大于等于阈值才可开仓
//        BigDecimal candleStickLength = subtract2.divide(new BigDecimal(lastCandleEntry5m.getOpen()), 6, BigDecimal.ROUND_DOWN).abs();
//
        boolean open = subtract2.compareTo(BigDecimal.ZERO) > 0
                && subtract3.divide(subtract4, 6, BigDecimal.ROUND_DOWN).compareTo(new BigDecimal("0.5")) > 0;
        BigDecimal nowAtr = new BigDecimal(atrs.get(atrs.size() - 1).floatValue());
        BigDecimal lastAtr = new BigDecimal(atrs.get(atrs.size() - 2).floatValue());
        BigDecimal last2Atr = new BigDecimal(atrs.get(atrs.size() - 3).floatValue());
        Boolean judgeAtr = lastAtr.divide(last2Atr, 6, BigDecimal.ROUND_DOWN).compareTo(new BigDecimal("1.1")) < 0;

        /*Boolean judgeLast = lastCandleEntry5m.getClose() > lastCandleEntry5m.getOpen() &&
                new BigDecimal(lastCandleEntry5m.getHigh()).subtract(new BigDecimal(lastCandleEntry5m.getClose())).divide(new BigDecimal(lastCandleEntry5m.getHigh()).subtract(new BigDecimal(lastCandleEntry5m.getLow())), 6, BigDecimal.ROUND_DOWN).compareTo(new BigDecimal("0.2")) < 0;

        Boolean judgeLast2 = last2CandleEntry5m.getClose() > last2CandleEntry5m.getOpen() &&
                new BigDecimal(last2CandleEntry5m.getHigh()).subtract(new BigDecimal(last2CandleEntry5m.getClose())).divide(new BigDecimal(last2CandleEntry5m.getHigh()).subtract(new BigDecimal(last2CandleEntry5m.getLow())), 6, BigDecimal.ROUND_DOWN).compareTo(new BigDecimal("0.2")) < 0;

        Boolean judgeLast3 = last3CandleEntry5m.getClose() > last3CandleEntry5m.getOpen() &&
                new BigDecimal(last3CandleEntry5m.getHigh()).subtract(new BigDecimal(last3CandleEntry5m.getClose())).divide(new BigDecimal(last3CandleEntry5m.getHigh()).subtract(new BigDecimal(last3CandleEntry5m.getLow())), 6, BigDecimal.ROUND_DOWN).compareTo(new BigDecimal("0.2")) < 0;
*/
        /*int startIndex = candleEntries.size() - 24;
        // 倒数元素的索引，subList的结束索引是排他的，所以需要+1
        int endIndex = candleEntries.size() - 3;
        List<MyCandleEntry> myCandleEntries = candleEntries.subList(startIndex, endIndex);
        TrendLines.TrendLine trendLines = TrendLines.calculateSupportAndResistanceLines(myCandleEntries);
        List<Double> supportPrices = trendLines.getSupportPrices();
        List<Double> resistancePrices = trendLines.getResistancePrices();
        boolean isTriangle = isTriangleForming(resistancePrices, supportPrices, myCandleEntries);
        Double currentCandleSupportPrice = supportPrices.get(supportPrices.size() - 1);
        Double currentCandleResistancePrice = resistancePrices.get(resistancePrices.size() - 1);
        currentCandleResistancePrice = atrs.get(atrs.size() - 4).doubleValue() * 1 + currentCandleResistancePrice;*/
        Boolean judge1 = last2CandleEntry5m.getOpen() > last2CandleEntry5m.getClose();
        Boolean judge2 = lastCandleEntry5m.getOpen() < lastCandleEntry5m.getClose();
        Boolean judge3 = lastCandleEntry5m.getClose() > last2CandleEntry5m.getHigh();
        int rsiTimeFrame2 = 2;
        BigDecimal lastRsi2 = getRsi(barSeries, rsiTimeFrame2, barSeries.getEndIndex() - 1);
        BigDecimal last2Rsi2 = getRsi(barSeries, rsiTimeFrame2, barSeries.getEndIndex() - 2);

        BigDecimal lowestPriceCurrent = getLowestPrice(candleEntries, candleEntries.size() - 1, 5);
        BigDecimal lowestPriceJudge = getLowestPrice(candleEntries, candleEntries.size() - 1, 30);

        /*JSONObject depth = feignService.getMarketPriceDepth(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getUserId(),
                quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin());
        JSONArray bids = depth.getJSONArray("bids");
        JSONArray asks = depth.getJSONArray("asks");
        JSONArray bid = (JSONArray) (bids.get(0));
        JSONArray ask = (JSONArray) (asks.get(0));
        BigDecimal bidPrice = new BigDecimal(String.valueOf(bid.get(0)));
        BigDecimal bidVolume = new BigDecimal(String.valueOf(bid.get(1)));*/
        //BigDecimal highestPriceJudge = getHighestPrice(candleEntries, candleEntries.size() - 1, 21);

        if (!quantBotDetailDTO.getCanOpen()) {
            if (new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue10) > 0) {
                quantBotDetailDTO.setCanOpen(true);
                quantBotDetailDTO.setMultipleAtr(new BigDecimal("0"));
            }
        }
        BigDecimal atrSlip = lastAtr.multiply(new BigDecimal("0"));
        if (/*lastRsi14.doubleValue() > 30
                && last2Rsi14.doubleValue() <= 30 &&*/
            /*&& lowestPriceCurrent.doubleValue() > lowestPriceJudge.doubleValue()*/
            /*lastRsi14.doubleValue() > 50*/
                /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue200) > 0
                        &&*/
                new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue10.subtract(atrSlip)) < 0
                        && quantBotDetailDTO.getCanOpen()
            /*new BigDecimal(last2CandleEntry5m.getClose()).compareTo(new BigDecimal(last2CandleEntry5m.getOpen())) < 0 &&*/
            /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue10) < 0*/
            /*lastRsi2.compareTo(new BigDecimal("10")) < 0*/
            /*&& new BigDecimal(lastCandleEntry5m.getHigh()).compareTo(lastEmaValue200.subtract(lastAtr.multiply(new BigDecimal("2.5")))) >= 0*/
            /*&& judgeEmaDegree*/
            /*&& lastAdx > 45*/
                /*&& new BigDecimal(last2CandleEntry5m.getClose()).compareTo(lastEmaValue200) < 0
                && new BigDecimal(last3CandleEntry5m.getClose()).compareTo(lastEmaValue200) < 0
                && new BigDecimal(last4CandleEntry5m.getClose()).compareTo(lastEmaValue200) < 0
                && new BigDecimal(last5CandleEntry5m.getClose()).compareTo(lastEmaValue200) < 0
                && new BigDecimal(last6CandleEntry5m.getClose()).compareTo(lastEmaValue200) < 0
                && new BigDecimal(last7CandleEntry5m.getClose()).compareTo(lastEmaValue200) < 0
                && new BigDecimal(last8CandleEntry5m.getClose()).compareTo(lastEmaValue200) < 0*/
            /*&& lastAdx > 40*/
            /*&& last2Adx <= 40*/
                /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue120) > 0
                        && new BigDecimal(lastCandleEntry5m.getLow()).compareTo(lastEmaValue120) < 0
                        & new BigDecimal(last2CandleEntry5m.getClose()).compareTo(last2EmaValue120) > 0
                        && new BigDecimal(last2CandleEntry5m.getLow()).compareTo(last2EmaValue120) < 0*/
            /*&& new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue200) > 0*/
                /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue200) > 0
                && judge1 && judge2 && judge3 && open
                && lastAtr.doubleValue() > last2Atr.doubleValue()*/
            /*&& lastRsi21.doubleValue() > 50*/
                /*isTriangle && trendLines.isRecentCandlesWithinTrend()
                && Double.valueOf(lastCandleEntry5m.getClose()) > currentCandleResistancePrice
                && Double.valueOf(lastCandleEntry5m.getClose()) > lastMaValue20.doubleValue()
                && Double.valueOf(lastCandleEntry5m.getClose()) > lastMaValue60.doubleValue()
                && Double.valueOf(lastCandleEntry5m.getClose()) > lastMaValue120.doubleValue()
                && Double.valueOf(lastCandleEntry5m.getClose()) > Double.valueOf(lastCandleEntry5m.getOpen())*/
            /*&& judgeAtr*/
            /*judgeLast && judgeLast2 && judgeLast3*/
                /*judgeAtr && open &&
                new BigDecimal(lastCandleEntry5m.getLow()).compareTo(judgeLowestPrice) <= 0*/
                /*subtract.compareTo(BigDecimal.ZERO) > 0
                && subtract1.compareTo(BigDecimal.ZERO) > 0
                && subtract2.compareTo(BigDecimal.ZERO) > 0
                && subtract.abs().compareTo(subtract1.abs()) < 0
                && subtract1.abs().compareTo(subtract2.abs()) < 0
                && lastCandleEntry5m.getClose() > lastCandleEntry5m.getOpen()
                && lastCandleEntry5m.getClose() > last2JudgePrice*/
            /* && lastJudgePrice > last2JudgePrice*/
            /*&& lastCandleEntry5m.getClose() < lastCandleEntry5m.getOpen()*/
                /*&& new BigDecimal(lastCandleEntry5m.getLow()).compareTo(judgeLowestPrice) < 0
                && new BigDecimal(lastCandleEntry5m.getClose()).compareTo(judgeLowestPrice) > 0*/
            /*lastRsi.compareTo(new BigDecimal("70")) > 0*/
            /*isBullEntry &&*//*judge2 && judge5 && judge6*//* && judgeStar*/
            /*judgeEma200*//*judgeA && judgeB && judgeC*//*judge4 &&*/ /*judgeRsi &&*/ /*&& judge4*/
                /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue200) > 0 &&
                        last3SupertrendResult.getDirection().isEqual(barSeries.numOf(1)) &&
                        new BigDecimal(last3CandleEntry5m.getLow()).compareTo(new BigDecimal(last3SupertrendResult.getSuperTrend().doubleValue())) < 0 &&
                        new BigDecimal(last3CandleEntry5m.getClose()).compareTo(new BigDecimal(last3SupertrendResult.getSuperTrend().doubleValue())) > 0 &&
                        last3Cci < -100 &&
                        last2Cci > -100 &&
                        new BigDecimal(lastCandleEntry5m.getClose()).compareTo(new BigDecimal(last3CandleEntry5m.getClose())) > 0 &&
                        new BigDecimal(lastCandleEntry5m.getClose()).compareTo(new BigDecimal(last3CandleEntry5m.getOpen())) > 0*/
                        /*last2Cci > 100 &&
                        last2K.isGreaterThan(barSeries.numOf(70)) &&
                        new BigDecimal(lastCandleEntry5m.getClose()).compareTo(new BigDecimal(lastCandleEntry5m.getOpen())) > 0 &&
                        lastSlowStochRsi.getK().isGreaterThan(lastSlowStochRsi.getD()) &&*/
            /*&& isBullEntry*//*
                        &&*/ /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue200) > 0 && lastAdx > 50*/ /*&& judgeEmaDegree*/
            /*&& lastPlusDI > lastMinusDI && lastSupertrendResult.getDirection().isEqual(barSeries.numOf(1))*/
                /*&& last2StochK.isLessThan(last2StochD) && lastStochK.isGreaterThan(lastStochD) &&
                lastStochK.isLessThan(barSeries.numOf(20)) && lastStochD.isLessThan(barSeries.numOf(20))*/
            /*&& new BigDecimal(lastCandleEntry5m.getClose()).compareTo(new BigDecimal(last2CandleEntry5m.getHigh())) > 0*/
                /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue20) > 0 &&
                new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue50) > 0*/
                        /*macdLast2 <= signalLast2 &&
                        macdLast > signalLast &&
                        judgeRsi*//* &&
                        (macdLast < 0 && macdLast2 < 0)*//* &&
                        judgeAtr && judgeAtr2*/
            /*judge2 && judge3*/ /*judge4*/
        ) {
            /*BigDecimal atrSlipRatio = atrSlip.divide(new BigDecimal(lastCandleEntry5m.getClose()), 6, BigDecimal.ROUND_DOWN);
            System.out.println("开多偏离率:" + atrSlipRatio);*/
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
            String progressTime = barSeries.getBar(barSeries.getEndIndex()).getBeginTime().format(formatter);
            BigDecimal nowOpen = new BigDecimal(nowCandleEntry5m.getOpen());
            /*BigDecimal[] lowestAndAtr = getLowestPriceAndAtr(atrs, candleEntries, candleEntries.size() - 2, judgePeriod);
            BigDecimal lowestPrice = lowestAndAtr[0];
            BigDecimal lowestAtr = lowestAndAtr[1];
            BigDecimal initStopLossPrice = lowestPrice.subtract(lowestAtr.multiply(new BigDecimal("1")));
            BigDecimal initStopLossRate = nowOpen.subtract(initStopLossPrice).divide(nowOpen, 6, BigDecimal.ROUND_DOWN).abs();*/
            BigDecimal temp = lastAtr.multiply(new BigDecimal("1")).divide(nowOpen, 6, BigDecimal.ROUND_DOWN);
            BigDecimal initStopLossPrice = (BigDecimal.ONE.subtract(temp)).multiply(nowOpen);
            BigDecimal initStopLossRate = nowOpen.subtract(initStopLossPrice).divide(nowOpen, 6, BigDecimal.ROUND_DOWN).abs();
            BigDecimal limitRate = nowOpen.subtract(initStopLossPrice).divide(nowOpen, 6, BigDecimal.ROUND_DOWN).abs();

            if (initStopLossRate.compareTo(SystemParamContants.stop_loss_max) > 0) {
                return new QuantBotDetailDTO[]{quantBotDetailDTO, null};
            }

//            BigDecimal[] highestAndAtr = getHighestPriceAndAtr(atrs, candleEntries5m, candleEntries5m.size() - 2, judgeRiseSpacePeriod);
//            BigDecimal highestPrice = highestAndAtr[0];
//            BigDecimal highestAtr = highestAndAtr[1];
//
//            if (highestPrice.compareTo(nowOpen.multiply(BigDecimal.ONE.add(initStopLossRate))) < 0) {
//               return new QuantBotDetailDTO[]{quantBotDetailDTO, null};
//            }

            BigDecimal initStopMax = (BigDecimal) redisTemplate.opsForValue().get("initStopMax:" + destinationCoins);
            List<BigDecimal> initStopMaxList = (List<BigDecimal>) redisTemplate.opsForValue().get("initStopMaxList:" + destinationCoins);
            if (initStopLossRate.compareTo(initStopMax) > 0) {
                initStopMax = initStopLossRate;
                initStopMaxList.add(initStopMax);
            }
            redisTemplate.opsForValue().set("initStopMax:" + destinationCoins, initStopMax);
            redisTemplate.opsForValue().set("initStopMaxList:" + destinationCoins, initStopMaxList);

            System.out.println(quantBotDetailDTO.getDestinationCoin() + " 多单开仓进度时间: " + progressTime + ",最大初始止损率:" + initStopMax + ",最大止损率集合:" + initStopMaxList);
            BigDecimal stopLossRate = initStopLossRate;
            BigDecimal stopWinRatio = initStopLossRate.multiply(new BigDecimal("1"));
            //BigDecimal stopWinRatio = new BigDecimal("0.005");
            BigDecimal breakEvenRate = stopWinRatio;
            //BigDecimal breakEvenRate = SystemParamContants.fee;
            //BigDecimal breakEvenRate = stopLossRate.negate();

            /*if (initStopLossRate.negate().compareTo(SystemParamContants.stop_loss_max.negate()) < 0) {
                initStopLossPrice = nowOpen.multiply(BigDecimal.ONE.subtract(SystemParamContants.stop_loss_max));
                stopLossRate = SystemParamContants.stop_loss_max;
            }*/

            PinBarCandlerStickDetailDTO pinBarCandlerStickDetailDTO = new PinBarCandlerStickDetailDTO();
            pinBarCandlerStickDetailDTO.setInitStopLossPrice(initStopLossPrice);
            pinBarCandlerStickDetailDTO.setStopLossPrice(initStopLossPrice);
            pinBarCandlerStickDetailDTO.setStopWinRate(stopWinRatio);
            pinBarCandlerStickDetailDTO.setBreakEvenRate(breakEvenRate);
            pinBarCandlerStickDetailDTO.setStopLossRate(stopLossRate);
            pinBarCandlerStickDetailDTO.setOpen(nowOpen.multiply(BigDecimal.ONE.add(slippage)));
            quantBotDetailDTO.setCurrentAddTime(String.valueOf(nowCandleEntry5m.getOpenTime()));
            //给移动止盈获取上次breakEventRate数据使用
            quantBotDetailDTO.setLastTimeRise(String.valueOf(pinBarCandlerStickDetailDTO.getBreakEvenRate()));

            quantBotDetailDTO.setPinBarCandlerStickDetailDTO(pinBarCandlerStickDetailDTO);

            return new QuantBotDetailDTO[]{quantBotDetailDTO, quantBotDetailDTO};
        } else {
            return new QuantBotDetailDTO[]{quantBotDetailDTO, null};
        }
    }


    /**
     * 开空趋势中突破判断
     */
    public QuantBotDetailDTO[] judgeTrendSellBreakThroughOpen(JSONObject candleStick, int atrPeriod, QuantBotDetailDTO quantBotDetailDTO, BarSeries barSeries, String destinationCoins, BigDecimal slippage) throws Exception {
        List<MyCandleEntry> candleEntries = getCandlerStick(candleStick);
        List<Num> atrs = getATR(barSeries, atrPeriod);
        MyCandleEntry nowCandleEntry5m = candleEntries.get(candleEntries.size() - 1);
        MyCandleEntry lastCandleEntry5m = candleEntries.get(candleEntries.size() - 2);
        MyCandleEntry last2CandleEntry5m = candleEntries.get(candleEntries.size() - 3);
        List<Entry> emas200 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA200);
        List<Entry> emas120 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA120);
        List<Entry> emas90 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA90);
        List<Entry> emas60 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA60);
        List<Entry> emas30 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA30);
        List<Entry> emas10 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA10);
        List<Entry> emas5 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA5);
        BigDecimal lastEmaValue120 = new BigDecimal((emas120.get(emas120.size() - 2)).getY());
        BigDecimal lastEmaValue90 = new BigDecimal((emas90.get(emas90.size() - 2)).getY());
        BigDecimal lastEmaValue60 = new BigDecimal((emas60.get(emas60.size() - 2)).getY());
        BigDecimal lastEmaValue30 = new BigDecimal((emas30.get(emas30.size() - 2)).getY());
        BigDecimal last2EmaValue30 = new BigDecimal((emas30.get(emas30.size() - 3)).getY());
        BigDecimal lastEmaValue200 = new BigDecimal((emas200.get(emas200.size() - 2)).getY());
        BigDecimal lastEmaValue10 = new BigDecimal((emas10.get(emas10.size() - 2)).getY());
        BigDecimal lastEmaValue5 = new BigDecimal((emas5.get(emas5.size() - 2)).getY());

        BigDecimal nowAtr = new BigDecimal(atrs.get(atrs.size() - 1).floatValue());
        BigDecimal lastAtr = new BigDecimal(atrs.get(atrs.size() - 2).floatValue());
        BigDecimal last2Atr = new BigDecimal(atrs.get(atrs.size() - 3).floatValue());

        if (!quantBotDetailDTO.getCanOpen()) {
            if (new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue10) < 0) {
                quantBotDetailDTO.setCanOpen(true);
                quantBotDetailDTO.setMultipleAtr(new BigDecimal("0"));
            }
        }
        int rsiTimeFrame = 14;
        BigDecimal lastRsi = getRsi(barSeries, rsiTimeFrame, barSeries.getEndIndex() - 1);
        BigDecimal last2Rsi = getRsi(barSeries, rsiTimeFrame, barSeries.getEndIndex() - 2);
        BigDecimal atrSlip = lastAtr.multiply(new BigDecimal("3"));

        /*int diBarCount = 14;
        int adxBarCount = 14;
        double lastAdx = getADX(barSeries, diBarCount, adxBarCount, barSeries.getEndIndex() - 1);*/
        BigDecimal[] lowestAndAtr = getLowestPriceAndAtr(atrs, candleEntries, candleEntries.size() - 3, 20);
        BigDecimal lowestPrice = lowestAndAtr[0];

        if (/*new BigDecimal(last2CandleEntry5m.getClose()).compareTo(lastEmaValue10.subtract(atrSlip)) < 0
                &&*/ /*new BigDecimal(lastCandleEntry5m.getOpen()).compareTo(lastEmaValue200) < 0
                && new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue200) > 0*/
            /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue30) < 0 &&*/
                /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue200) <= 0 &&
                        new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue120) <= 0 &&
                        new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue60) <= 0 &&
                        new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue10) <= 0*/
            /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue60) < 0 &&*/
                new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lowestPrice) < 0
            /*lastRsi.doubleValue() <= 40 && last2Rsi.doubleValue() > 40*/
            /*lastRsi.doubleValue() > 30*/

                /*lastRsi.doubleValue() <= 70 && last2Rsi.doubleValue() > 70
                        && new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue120) < 0*/

            /*&& new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue30) > 0*/
                /*&&
                lastRsi.compareTo(new BigDecimal("90")) <= 0
                        && last2Rsi.compareTo(new BigDecimal("90")) > 0*/
            /*&& lastEmaValue10.compareTo(lastEmaValue60) < 0*/
            /*&& lastRsi.doubleValue() > 90*/
            /*&& quantBotDetailDTO.getCanOpen()*/
        ) {
            /*BigDecimal atrSlipRatio = atrSlip.divide(new BigDecimal(lastCandleEntry5m.getClose()), 6, BigDecimal.ROUND_DOWN);
            System.out.println("开空偏离率:" + atrSlipRatio);*/
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
            String progressTime = barSeries.getBar(barSeries.getEndIndex()).getBeginTime().format(formatter);
            BigDecimal nowOpen = new BigDecimal(nowCandleEntry5m.getOpen());
            BigDecimal[] highestPriceAndAtr = getHighestPriceAndAtr(atrs, candleEntries, candleEntries.size() - 2, 20);
            BigDecimal highestPrice = highestPriceAndAtr[0];
            BigDecimal highestAtr = highestPriceAndAtr[1];
            BigDecimal initStopLossPrice = highestPrice.add(highestAtr.multiply(new BigDecimal("0")));
            BigDecimal initStopLossRate = initStopLossPrice.subtract(nowOpen).divide(nowOpen, 6, BigDecimal.ROUND_DOWN).abs();
            /*BigDecimal[] lowestAndAtr = getLowestPriceAndAtr(atrs, candleEntries, candleEntries.size() - 2, 1);
            BigDecimal lowestPrice = lowestAndAtr[0];
            BigDecimal lowestAtr = lowestAndAtr[1];
            BigDecimal initStopLossPrice = lowestPrice.subtract(lowestAtr.multiply(new BigDecimal("0")));
            BigDecimal initStopLossRate = nowOpen.subtract(initStopLossPrice).divide(nowOpen, 6, BigDecimal.ROUND_DOWN).abs();*/

            /*BigDecimal temp = new BigDecimal("0.05");
            BigDecimal initStopLossPrice = (BigDecimal.ONE.add(temp)).multiply(nowOpen);
            BigDecimal initStopLossRate = initStopLossPrice.subtract(nowOpen).divide(nowOpen, 6, BigDecimal.ROUND_DOWN).abs();*/
            BigDecimal limitRate = initStopLossPrice.subtract(nowOpen).divide(nowOpen, 6, BigDecimal.ROUND_DOWN).abs();
            if (initStopLossRate.compareTo(SystemParamContants.stop_loss_max) > 0) {
                return new QuantBotDetailDTO[]{quantBotDetailDTO, null};
            }

            BigDecimal initStopMax = (BigDecimal) redisTemplate.opsForValue().get("initStopMax:" + destinationCoins);
            List<BigDecimal> initStopMaxList = (List<BigDecimal>) redisTemplate.opsForValue().get("initStopMaxList:" + destinationCoins);
            if (initStopLossRate.compareTo(initStopMax) > 0) {
                initStopMax = initStopLossRate;
                initStopMaxList.add(initStopMax);
            }
            redisTemplate.opsForValue().set("initStopMax:" + destinationCoins, initStopMax);
            redisTemplate.opsForValue().set("initStopMaxList:" + destinationCoins, initStopMaxList);

            BigDecimal stopLossRate = initStopLossRate.negate();
            BigDecimal stopWinRatio = initStopLossRate.multiply(new BigDecimal("1"));
            //BigDecimal stopWinRatio = new BigDecimal("0.005");
            //BigDecimal breakEvenRate = stopWinRatio;
            BigDecimal breakEvenRate = new BigDecimal("0.01");
            //BigDecimal breakEvenRate = stopLossRate.negate();

            PinBarCandlerStickDetailDTO pinBarCandlerStickDetailDTO = new PinBarCandlerStickDetailDTO();
            pinBarCandlerStickDetailDTO.setInitStopLossPrice(initStopLossPrice);
            pinBarCandlerStickDetailDTO.setStopLossPrice(initStopLossPrice);
            pinBarCandlerStickDetailDTO.setStopWinRate(stopWinRatio);
            pinBarCandlerStickDetailDTO.setBreakEvenRate(breakEvenRate);
            pinBarCandlerStickDetailDTO.setStopLossRate(stopLossRate);
            pinBarCandlerStickDetailDTO.setOpen(nowOpen.multiply(BigDecimal.ONE.subtract(slippage)));
            quantBotDetailDTO.setCurrentAddTime(String.valueOf(nowCandleEntry5m.getOpenTime()));

            //给移动止盈获取上次breakEventRate数据使用
            quantBotDetailDTO.setLastTimeRise(String.valueOf(pinBarCandlerStickDetailDTO.getBreakEvenRate()));

            quantBotDetailDTO.setPinBarCandlerStickDetailDTO(pinBarCandlerStickDetailDTO);

            System.out.println(quantBotDetailDTO.getDestinationCoin() + " 空单开仓进度时间: " + progressTime + ",最大初始止损率:" + initStopMax + ",开单均价:" + pinBarCandlerStickDetailDTO.getOpen().setScale(6, RoundingMode.HALF_UP));

            return new QuantBotDetailDTO[]{quantBotDetailDTO, quantBotDetailDTO};
        } else {
            return new QuantBotDetailDTO[]{quantBotDetailDTO, null};
        }
    }

    public QuantBotDetailDTO[] judgeTrendSellBreakThroughOpen2(JSONObject candleStick, int atrPeriod, QuantBotDetailDTO quantBotDetailDTO, BarSeries barSeries, String destinationCoins, BigDecimal slippage) throws Exception {
        int shortPeriod = 12;
        int longPeriod = 26;
        int signalPeriod = 9;
        int judgePeriod = 2;
        int judgeRiseSpacePeriod = 20;

        List<MyCandleEntry> candleEntries = getCandlerStick(candleStick);
        List<Num> atrs = getATR(barSeries, atrPeriod);
        MyCandleEntry nowCandleEntry5m = candleEntries.get(candleEntries.size() - 1);
        MyCandleEntry lastCandleEntry5m = candleEntries.get(candleEntries.size() - 2);
        MyCandleEntry last2CandleEntry5m = candleEntries.get(candleEntries.size() - 3);
        MyCandleEntry last3CandleEntry5m = candleEntries.get(candleEntries.size() - 4);
        MyCandleEntry last4CandleEntry5m = candleEntries.get(candleEntries.size() - 5);
        MyCandleEntry last5CandleEntry5m = candleEntries.get(candleEntries.size() - 6);

        MyCandleEntry last6CandleEntry5m = candleEntries.get(candleEntries.size() - 7);
        MyCandleEntry last7CandleEntry5m = candleEntries.get(candleEntries.size() - 8);
        MyCandleEntry last8CandleEntry5m = candleEntries.get(candleEntries.size() - 9);
        List<Entry> emas200 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA200);
        List<Entry> emas120 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA120);
        List<Entry> emas90 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA90);
        List<Entry> emas60 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA60);
        List<Entry> emas20 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA20);
        List<Entry> emas10 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA10);
        List<Entry> emas5 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA5);
        BigDecimal lastEmaValue120 = new BigDecimal((emas120.get(emas120.size() - 2)).getY());
        BigDecimal last2EmaValue120 = new BigDecimal((emas120.get(emas120.size() - 3)).getY());
        BigDecimal lastEmaValue90 = new BigDecimal((emas90.get(emas90.size() - 2)).getY());
        BigDecimal lastEmaValue60 = new BigDecimal((emas60.get(emas60.size() - 2)).getY());
        BigDecimal lastEmaValue20 = new BigDecimal((emas20.get(emas20.size() - 2)).getY());
        BigDecimal lastEmaValue200 = new BigDecimal((emas200.get(emas200.size() - 2)).getY());
        BigDecimal lastEmaValue10 = new BigDecimal((emas10.get(emas10.size() - 2)).getY());
        BigDecimal lastEmaValue5 = new BigDecimal((emas5.get(emas5.size() - 2)).getY());

        float[] mas120 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA120);
        float[] mas60 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA60);
        float[] mas20 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA20);
        BigDecimal lastMaValue120 = new BigDecimal(mas120[1]);
        BigDecimal lastMaValue60 = new BigDecimal(mas60[1]);
        BigDecimal lastMaValue20 = new BigDecimal(mas20[1]);
        /*Boolean judgeEma200 = true;
        for (int i = 0; i < judgePeriod; i++) {
            MyCandleEntry chooseCandleEntry5m = candleEntries.get(candleEntries.size() - 2 - i);
            BigDecimal open = new BigDecimal(chooseCandleEntry5m.getOpen());
            BigDecimal close = new BigDecimal(chooseCandleEntry5m.getClose());
            BigDecimal max = open.compareTo(close) > 0 ? open : close;
            BigDecimal chooseEmaValue200 = new BigDecimal((emas200.get(emas200.size() - 2 - i)).getY());
            if (max.compareTo(chooseEmaValue200) > 0) {
                judgeEma200 = false;
                break;
            }
        }*/

        List<Num>[] macd_signal_value = getMACD_signal_value(barSeries, shortPeriod, longPeriod, signalPeriod);
        List<Num> macdvalues = macd_signal_value[0];
        /*List<Num> signalvalues = macd_signal_value[1];

        double macdLast = macdvalues.get(candleEntries.size() - 2 - signalPeriod).doubleValue();
        double macdLast2 = macdvalues.get(candleEntries.size() - 3 - signalPeriod).doubleValue();

        double signalLast = signalvalues.get(candleEntries.size() - 2 - signalPeriod).doubleValue();
        double signalLast2 = signalvalues.get(candleEntries.size() - 3 - signalPeriod).doubleValue();

        BigDecimal atrLast = new BigDecimal(atrs.get(atrs.size() - 2).floatValue());
        BigDecimal atrLast2 = new BigDecimal(atrs.get(atrs.size() - 3).floatValue());
        BigDecimal atrLast3 = new BigDecimal(atrs.get(atrs.size() - 4).floatValue());
        Boolean judgeAtr = atrLast.subtract(atrLast2).divide(atrLast2, 6, BigDecimal.ROUND_DOWN).compareTo(new BigDecimal("0.1")) < 0;
        Boolean judgeAtr2 = atrLast2.subtract(atrLast3).divide(atrLast3, 6, BigDecimal.ROUND_DOWN).compareTo(new BigDecimal("0.1")) < 0;
*/

        //boolean isBearEntry = isBearEntry(candleEntries, macdvalues, signalPeriod, judgePeriod);
        /*Boolean judge = (last2CandleEntry5m.getClose() > last2CandleEntry5m.getOpen()) &&
                (last3CandleEntry5m.getClose() > last3CandleEntry5m.getOpen()) &&
                (last4CandleEntry5m.getClose() > last4CandleEntry5m.getOpen()) &&
                (last5CandleEntry5m.getClose() > last5CandleEntry5m.getOpen()) &&
                (lastCandleEntry5m.getClose() < last5CandleEntry5m.getLow());*/

        /*Boolean judge = (lastCandleEntry5m.getClose() < lastCandleEntry5m.getOpen())&&
                (last2CandleEntry5m.getClose() > last2CandleEntry5m.getOpen())&&
                (lastCandleEntry5m.getClose() < last2CandleEntry5m.getOpen());*/

        /*BigDecimal subtract1 = new BigDecimal(lastCandleEntry5m.getHigh()).subtract(new BigDecimal(lastCandleEntry5m.getOpen()));
        BigDecimal subtract2 = new BigDecimal(lastCandleEntry5m.getHigh()).subtract(new BigDecimal(lastCandleEntry5m.getLow()));
        if (subtract2.compareTo(BigDecimal.ZERO) == 0) {
            return null;
        }
        Boolean judge2 = (subtract1.divide(subtract2, 6, BigDecimal.ROUND_DOWN)).compareTo(new BigDecimal("0.6")) > 0;
        Boolean judge3 = new BigDecimal(lastCandleEntry5m.getClose()).compareTo(new BigDecimal(lastCandleEntry5m.getOpen())) < 0;*/
        /*List<Entry> emas13 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA13);
        List<Entry> emas21 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA21);
        List<Entry> emas55 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA55);
        BigDecimal lastEmaValue13 = new BigDecimal((emas13.get(emas13.size() - 2)).getY());
        BigDecimal lastEmaValue21 = new BigDecimal((emas21.get(emas21.size() - 2)).getY());
        BigDecimal lastEmaValue55 = new BigDecimal((emas55.get(emas55.size() - 2)).getY());
        BigDecimal last2EmaValue13 = new BigDecimal((emas13.get(emas13.size() - 3)).getY());
        BigDecimal last2EmaValue21 = new BigDecimal((emas21.get(emas21.size() - 3)).getY());
        BigDecimal last2EmaValue55 = new BigDecimal((emas55.get(emas55.size() - 3)).getY());
        Boolean judge4 = lastEmaValue21.compareTo(lastEmaValue55) < 0 &&
                last2EmaValue21.compareTo(last2EmaValue55) > 0 &&
                lastEmaValue13.compareTo(lastEmaValue21) < 0;*/
        /*float last2Body = last2CandleEntry5m.getClose() - last2CandleEntry5m.getOpen();
        float last3Body = last3CandleEntry5m.getClose() - last3CandleEntry5m.getOpen();
        float last4Body = last4CandleEntry5m.getClose() - last4CandleEntry5m.getOpen();
        Boolean judge2 = (last2Body > 0) && (last3Body > 0) && (last4Body > 0);
        Boolean judge5 = new BigDecimal(last2CandleEntry5m.getClose()).compareTo(new BigDecimal(last2CandleEntry5m.getOpen())) > 0 &&
                new BigDecimal(lastCandleEntry5m.getClose()).compareTo(new BigDecimal(lastCandleEntry5m.getOpen())) < 0;
        Boolean judge6 = new BigDecimal(last2CandleEntry5m.getClose()).compareTo(new BigDecimal(lastCandleEntry5m.getOpen())) < 0 &&
                new BigDecimal(last2CandleEntry5m.getOpen()).compareTo(new BigDecimal(lastCandleEntry5m.getClose())) > 0;
        Boolean judgeStar = checkStar(lastCandleEntry5m.getClose(), lastCandleEntry5m.getOpen(),
                lastCandleEntry5m.getHigh(), lastCandleEntry5m.getLow());*/

        /*int rsiTimeFrame21 = 21;
        BigDecimal lastRsi21 = getRsi(barSeries, rsiTimeFrame21, barSeries.getEndIndex() - 1);
        BigDecimal last2Rsi21 = getRsi(barSeries, rsiTimeFrame21, barSeries.getEndIndex() - 2);

        int rsiTimeFrame55 = 55;
        BigDecimal lastRsi55 = getRsi(barSeries, rsiTimeFrame55, barSeries.getEndIndex() - 1);
        BigDecimal last2Rsi55 = getRsi(barSeries, rsiTimeFrame55, barSeries.getEndIndex() - 2);

        Boolean judgeRsi = lastRsi21.compareTo(lastRsi55) < 0 && last2Rsi21.compareTo(last2Rsi55) > 0;*/

        /*double macdLast3 = macdvalues.get(candleEntries.size() - 4 - signalPeriod).doubleValue();
        double macdLast4 = macdvalues.get(candleEntries.size() - 5 - signalPeriod).doubleValue();
        double[] macdValues = {macdLast4, macdLast3, macdLast2, macdLast};*/

        //1.（上一根K线最低价-取30根前的K线最低价）/取30根前的K线最低价 > 0
        /*MyCandleEntry last30CandleEntry5m = candleEntries.get(candleEntries.size() - 31);
        Boolean judgeA = new BigDecimal(lastCandleEntry5m.getLow()).subtract(new BigDecimal(last30CandleEntry5m.getLow())).
                divide(new BigDecimal(last30CandleEntry5m.getLow()), 6, BigDecimal.ROUND_DOWN).compareTo(new BigDecimal("0")) > 0;
        //2.（上根RSI - 上上根RSI）/上上根RSI < 0
        int rsiTimeFrame = 14;
        BigDecimal lastRsi = getRsi(barSeries, rsiTimeFrame, barSeries.getEndIndex() - 1);
        BigDecimal last2Rsi = getRsi(barSeries, rsiTimeFrame, barSeries.getEndIndex() - 2);
        Boolean judgeB = lastRsi.subtract(last2Rsi).divide(last2Rsi, 6, BigDecimal.ROUND_DOWN).compareTo(new BigDecimal("0")) < 0;
        //3.上根RSI > 45
        Boolean judgeC = lastRsi.compareTo(new BigDecimal("45")) > 0;*/

        int diBarCount = 14;
        int adxBarCount = 14;
        double lastAdx = getADX(barSeries, diBarCount, adxBarCount, barSeries.getEndIndex() - 1);
        double last2Adx = getADX(barSeries, diBarCount, adxBarCount, barSeries.getEndIndex() - 2);
        /*double last2Adx = getADX(barSeries, diBarCount, adxBarCount, barSeries.getEndIndex() - 2);
        double lastPlusDI = getPlusDI(barSeries, diBarCount, barSeries.getEndIndex() - 1);
        double lastMinusDI = getMinusDI(barSeries, diBarCount, barSeries.getEndIndex() - 1);*/
        //double last2PlusDI = getPlusDI(barSeries, diBarCount, barSeries.getEndIndex() - 2);
        //double last2MinusDI = getMinusDI(barSeries, diBarCount, barSeries.getEndIndex() - 2);
        /*float factor = 3f;
        int superTrendAtrPeriod = 10;
        SupertrendResult lastSupertrendResult = calculateSupertrend(barSeries, factor, superTrendAtrPeriod, barSeries.getEndIndex() - 1);*/
        //SupertrendResult last2SupertrendResult = calculateSupertrend(barSeries, factor, superTrendAtrPeriod, barSeries.getEndIndex() - 2);
        //SupertrendResult last3SupertrendResult = calculateSupertrend(barSeries, factor, superTrendAtrPeriod, barSeries.getEndIndex() - 3);

        /*int cciPeriod = 20;
        double lastCci = getCCI(barSeries, cciPeriod, barSeries.getEndIndex() - 1);
        double last2Cci = getCCI(barSeries, cciPeriod, barSeries.getEndIndex() - 2);
        double last3Cci = getCCI(barSeries, cciPeriod, barSeries.getEndIndex() - 3);*/

        int rsiBarCount = 14;
        int stockBarCount = 14;
        int kPeriod = 6;
        int dPeriod = 6;
        Num[] lastStochRsi = getStochRsi(barSeries, rsiBarCount, stockBarCount, kPeriod, dPeriod, barSeries.getEndIndex() - 1);
        Num[] last2StochRsi = getStochRsi(barSeries, rsiBarCount, stockBarCount, kPeriod, dPeriod, barSeries.getEndIndex() - 2);
        Num lastStochK = lastStochRsi[0];
        Num lastStochD = lastStochRsi[1];
        Num last2StochK = last2StochRsi[0];
        Num last2StochD = last2StochRsi[1];

        /*int length = 10;
        int smoothK = 6;
        int smoothD = 3;
        SlowStochRsiResult lastSlowStochRsi = getSlowStochRsi(barSeries, length, smoothK, smoothD, barSeries.getEndIndex() - 1);*/

        /*int rsiTimeFrame = 14;
        BigDecimal lastRsi = getRsi(barSeries, rsiTimeFrame, barSeries.getEndIndex() - 1);*/

        /*double lastOBV = getOBV(barSeries, barSeries.getEndIndex() - 1);
        double last2OBV = getOBV(barSeries, barSeries.getEndIndex() - 2);*/

        /*List<Entry> emas3 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA3);
        BigDecimal lastEmaValue3 = new BigDecimal((emas3.get(emas3.size() - 2)).getY());
        BigDecimal last2EmaValue3 = new BigDecimal((emas3.get(emas3.size() - 3)).getY());
        BigDecimal degreeEma3 = FinanceIndicatorsUtil.getMaDegree(lastEmaValue3, last2EmaValue3);

        List<Entry> emas6 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA6);
        BigDecimal lastEmaValue6 = new BigDecimal((emas6.get(emas6.size() - 2)).getY());
        BigDecimal last2EmaValue6 = new BigDecimal((emas6.get(emas6.size() - 3)).getY());
        BigDecimal degreeEma6 = FinanceIndicatorsUtil.getMaDegree(lastEmaValue6, last2EmaValue6);

        List<Entry> emas9 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA9);
        BigDecimal lastEmaValue9 = new BigDecimal((emas9.get(emas9.size() - 2)).getY());
        BigDecimal last2EmaValue9 = new BigDecimal((emas9.get(emas9.size() - 3)).getY());
        BigDecimal degreeEma9 = FinanceIndicatorsUtil.getMaDegree(lastEmaValue9, last2EmaValue9);

        List<Entry> emas12 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA12);
        BigDecimal lastEmaValue12 = new BigDecimal((emas12.get(emas12.size() - 2)).getY());
        BigDecimal last2EmaValue12 = new BigDecimal((emas12.get(emas12.size() - 3)).getY());
        BigDecimal degreeEma12 = FinanceIndicatorsUtil.getMaDegree(lastEmaValue12, last2EmaValue12);

        List<Entry> emas20 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA20);
        BigDecimal lastEmaValue20 = new BigDecimal((emas20.get(emas20.size() - 2)).getY());
        BigDecimal last2EmaValue20 = new BigDecimal((emas20.get(emas20.size() - 3)).getY());
        BigDecimal degreeEma20 = FinanceIndicatorsUtil.getMaDegree(lastEmaValue20, last2EmaValue20);

        Boolean judgeEmaDegree = degreeEma3.compareTo(BigDecimal.ZERO) < 0 && degreeEma6.compareTo(BigDecimal.ZERO) < 0 &&
                degreeEma9.compareTo(BigDecimal.ZERO) < 0 && degreeEma12.compareTo(BigDecimal.ZERO) < 0 && degreeEma20.compareTo(BigDecimal.ZERO) < 0;*/
        BigDecimal nowAtr = new BigDecimal(atrs.get(atrs.size() - 1).floatValue());
        BigDecimal lastAtr = new BigDecimal(atrs.get(atrs.size() - 2).floatValue());
        BigDecimal last2Atr = new BigDecimal(atrs.get(atrs.size() - 3).floatValue());
        Boolean judgeAtr = lastAtr.divide(last2Atr, 6, BigDecimal.ROUND_DOWN).compareTo(new BigDecimal("1.1")) < 0;
        //上根蜡烛开盘价-上根蜡烛收盘价
        BigDecimal subtract2 = new BigDecimal(lastCandleEntry5m.getOpen()).subtract(new BigDecimal(lastCandleEntry5m.getClose()));
        //上根蜡烛最高点-上根蜡烛开盘价
        BigDecimal subtract3 = new BigDecimal(lastCandleEntry5m.getHigh()).subtract(new BigDecimal(lastCandleEntry5m.getOpen()));
        //上根蜡烛最高点-上根蜡烛最低点
        BigDecimal subtract4 = new BigDecimal(lastCandleEntry5m.getHigh()).subtract(new BigDecimal(lastCandleEntry5m.getLow()));

        //上根蜡烛图实体大于等于阈值才可开仓
        BigDecimal candleStickLength = subtract2.divide(new BigDecimal(lastCandleEntry5m.getOpen()), 6, BigDecimal.ROUND_DOWN).abs();

        boolean open = (subtract2.compareTo(BigDecimal.ZERO) > 0) && (subtract3.divide(subtract4, 6, BigDecimal.ROUND_DOWN).compareTo(new BigDecimal("0.5")) > 0);
//        BigDecimal lastAtr = new BigDecimal(atrs.get(atrs.size() - 2).floatValue());
//        BigDecimal last2Atr = new BigDecimal(atrs.get(atrs.size() - 3).floatValue());
//        Boolean judgeAtr = lastAtr.divide(last2Atr, 6, BigDecimal.ROUND_DOWN).compareTo(new BigDecimal("1.05")) > 0;
        /*Boolean judgeLast = lastCandleEntry5m.getClose() < lastCandleEntry5m.getOpen() &&
                new BigDecimal(lastCandleEntry5m.getClose()).subtract(new BigDecimal(lastCandleEntry5m.getLow())).divide(new BigDecimal(lastCandleEntry5m.getHigh()).subtract(new BigDecimal(lastCandleEntry5m.getLow())), 6, BigDecimal.ROUND_DOWN).compareTo(new BigDecimal("0.2")) < 0;

        Boolean judgeLast2 = last2CandleEntry5m.getClose() < last2CandleEntry5m.getOpen() &&
                new BigDecimal(last2CandleEntry5m.getClose()).subtract(new BigDecimal(last2CandleEntry5m.getLow())).divide(new BigDecimal(last2CandleEntry5m.getHigh()).subtract(new BigDecimal(last2CandleEntry5m.getLow())), 6, BigDecimal.ROUND_DOWN).compareTo(new BigDecimal("0.2")) < 0;

        Boolean judgeLast3 = last3CandleEntry5m.getClose() < last3CandleEntry5m.getOpen() &&
                new BigDecimal(last3CandleEntry5m.getClose()).subtract(new BigDecimal(last3CandleEntry5m.getLow())).divide(new BigDecimal(last3CandleEntry5m.getHigh()).subtract(new BigDecimal(last3CandleEntry5m.getLow())), 6, BigDecimal.ROUND_DOWN).compareTo(new BigDecimal("0.2")) < 0;
*/
        /*int startIndex = candleEntries.size() - 24;
        // 倒数元素的索引，subList的结束索引是排他的，所以需要+1
        int endIndex = candleEntries.size() - 3;
        List<MyCandleEntry> myCandleEntries = candleEntries.subList(startIndex, endIndex);
        TrendLines.TrendLine trendLines = TrendLines.calculateSupportAndResistanceLines(myCandleEntries);
        List<Double> supportPrices = trendLines.getSupportPrices();
        List<Double> resistancePrices = trendLines.getResistancePrices();
        boolean isTriangle = isTriangleForming(resistancePrices, supportPrices, myCandleEntries);
        Double currentCandleSupportPrice = supportPrices.get(supportPrices.size() - 1);
        Double currentCandleResistancePrice = resistancePrices.get(resistancePrices.size() - 1);
        currentCandleSupportPrice = currentCandleSupportPrice - atrs.get(atrs.size() - 4).doubleValue() * 1;*/
        Boolean judge1 = last2CandleEntry5m.getOpen() < last2CandleEntry5m.getClose();
        Boolean judge2 = lastCandleEntry5m.getOpen() > lastCandleEntry5m.getClose();
        Boolean judge3 = lastCandleEntry5m.getClose() < last2CandleEntry5m.getLow();
        int rsiTimeFrame2 = 2;
        BigDecimal lastRsi2 = getRsi(barSeries, rsiTimeFrame2, barSeries.getEndIndex() - 1);
        BigDecimal last2Rsi2 = getRsi(barSeries, rsiTimeFrame2, barSeries.getEndIndex() - 2);

        /*BigDecimal highestPriceCurrent = getHighestPrice(candleEntries, candleEntries.size() - 1, 5);
        BigDecimal highestPriceJudge = getHighestPrice(candleEntries, candleEntries.size() - 1, 30);*/
        //BigDecimal lowestPriceJudge = getLowestPrice(candleEntries, candleEntries.size() - 1, 21);

        if (!quantBotDetailDTO.getCanOpen()) {
            if (new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue10) < 0) {
                quantBotDetailDTO.setCanOpen(true);
                quantBotDetailDTO.setMultipleAtr(new BigDecimal("0"));
            }
        }
        BigDecimal atrSlip = lastAtr.multiply(new BigDecimal("0"));
        if (/*lastRsi14.doubleValue() < 70
                && last2Rsi14.doubleValue() >= 70 &&*/
            /*&& highestPriceCurrent.doubleValue() < highestPriceJudge.doubleValue()*/
                /*lastRsi14.doubleValue() < 50
                &&*/
                /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue200) < 0
                        &&*/
                new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue10.add(atrSlip)) > 0
                        && quantBotDetailDTO.getCanOpen()
            /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(new BigDecimal(lastCandleEntry5m.getOpen())) > 0*/
            /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue200) < 0 &&*/
            /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue10) > 0 &&*/
            /*lastRsi2.compareTo(new BigDecimal("90")) > 0*/
            /*new BigDecimal(last2CandleEntry5m.getClose()).compareTo(new BigDecimal(last2CandleEntry5m.getOpen())) > 0 &&*/
            /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue10) > 0*/
            /*&& judgeEmaDegree*/
            /*&& lastAdx > 45*/
                /*&& new BigDecimal(last2CandleEntry5m.getClose()).compareTo(lastEmaValue200) > 0
                && new BigDecimal(last3CandleEntry5m.getClose()).compareTo(lastEmaValue200) > 0
                && new BigDecimal(last4CandleEntry5m.getClose()).compareTo(lastEmaValue200) > 0
                && new BigDecimal(last5CandleEntry5m.getClose()).compareTo(lastEmaValue200) > 0
                && new BigDecimal(last6CandleEntry5m.getClose()).compareTo(lastEmaValue200) > 0
                && new BigDecimal(last7CandleEntry5m.getClose()).compareTo(lastEmaValue200) > 0
                && new BigDecimal(last8CandleEntry5m.getClose()).compareTo(lastEmaValue200) > 0*/
            /*&& lastAdx > 40*/
            /* && last2Adx <= 40*/
                /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue120) < 0
                        && new BigDecimal(lastCandleEntry5m.getHigh()).compareTo(lastEmaValue120) > 0
                        & new BigDecimal(last2CandleEntry5m.getClose()).compareTo(last2EmaValue120) < 0
                        && new BigDecimal(last2CandleEntry5m.getHigh()).compareTo(last2EmaValue120) > 0*/
            /*&& new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue200) < 0*/
                /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue200) < 0
                && judge1 && judge2 && judge3 && open
                && lastAtr.doubleValue() > last2Atr.doubleValue()*/
            /*&& lastRsi21.doubleValue() < 50*/
                /*isTriangle && trendLines.isRecentCandlesWithinTrend()
                && Double.valueOf(lastCandleEntry5m.getClose()) < currentCandleSupportPrice
                && Double.valueOf(lastCandleEntry5m.getClose()) < lastMaValue20.doubleValue()
                && Double.valueOf(lastCandleEntry5m.getClose()) < lastMaValue60.doubleValue()
                && Double.valueOf(lastCandleEntry5m.getClose()) < lastMaValue120.doubleValue()
                && Double.valueOf(lastCandleEntry5m.getClose()) < Double.valueOf(lastCandleEntry5m.getOpen())*/
            /*&& judgeAtr*/
            /*judgeLast && judgeLast2 && judgeLast3*/
                /*subtract.compareTo(BigDecimal.ZERO) > 0
                && subtract1.compareTo(BigDecimal.ZERO) > 0
                && subtract2.compareTo(BigDecimal.ZERO) > 0
                && subtract.abs().compareTo(subtract1.abs()) < 0
                && subtract1.abs().compareTo(subtract2.abs()) < 0
                && lastCandleEntry5m.getClose() < lastCandleEntry5m.getOpen()
                && lastCandleEntry5m.getClose() < last2JudgePrice*/
                /*new BigDecimal(lastCandleEntry5m.getHigh()).compareTo(judgeHighestPrice) > 0
                        && new BigDecimal(lastCandleEntry5m.getClose()).compareTo(judgeHighestPrice) < 0*/
            /*lastRsi.compareTo(new BigDecimal("30")) < 0*/
            /*isBearEntry &&*//*judge2 && judge5 && judge6*//* && judgeStar*/
            /*judgeEma200*//*judgeA && judgeB && judgeC*//*judge4 &&*/ /*judgeRsi &&*/ /*&& judge4*/
                /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue200) < 0 &&
                        last3SupertrendResult.getDirection().isEqual(barSeries.numOf(-1)) &&
                        new BigDecimal(last3CandleEntry5m.getHigh()).compareTo(new BigDecimal(last3SupertrendResult.getSuperTrend().doubleValue())) > 0 &&
                        new BigDecimal(last3CandleEntry5m.getClose()).compareTo(new BigDecimal(last3SupertrendResult.getSuperTrend().doubleValue())) < 0 &&
                        last3Cci > 100 &&
                        last2Cci < 100 &&
                        new BigDecimal(lastCandleEntry5m.getClose()).compareTo(new BigDecimal(last3CandleEntry5m.getClose())) < 0 &&
                        new BigDecimal(lastCandleEntry5m.getClose()).compareTo(new BigDecimal(last3CandleEntry5m.getOpen())) < 0*/
                        /*last2Cci < -100 &&
                        last2K.isLessThan(barSeries.numOf(30)) &&
                        new BigDecimal(lastCandleEntry5m.getClose()).compareTo(new BigDecimal(lastCandleEntry5m.getOpen())) < 0 &&
                        lastSlowStochRsi.getK().isLessThan(lastSlowStochRsi.getD()) &&*/
            /*isBearEntry &&*//*
                        &&*/
            /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue200) < 0 && lastAdx > 50*/ /*&& judgeEmaDegree*/
            /*&& lastMinusDI > lastPlusDI && lastSupertrendResult.getDirection().isEqual(barSeries.numOf(-1))*/
                        /*&& last2StochK.isGreaterThan(last2StochD) && lastStochK.isLessThan(lastStochD)
                        && lastStochK.isGreaterThan(barSeries.numOf(80)) && lastStochD.isGreaterThan(barSeries.numOf(80))*/
            /*&& new BigDecimal(lastCandleEntry5m.getClose()).compareTo(new BigDecimal(last2CandleEntry5m.getLow())) < 0*/
            /*new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue20) < 0 &&
                new BigDecimal(lastCandleEntry5m.getClose()).compareTo(lastEmaValue50) < 0*/
                        /*macdLast2 >= signalLast2 &&
                        macdLast < signalLast &&
                        judgeRsi*//* &&
                        (macdLast > 0 && macdLast2 > 0)*//* &&
                        judgeAtr && judgeAtr2*/
            /*judge2 && judge3*/ /*judge4*/
        ) {
            /*BigDecimal atrSlipRatio = atrSlip.divide(new BigDecimal(lastCandleEntry5m.getClose()), 6, BigDecimal.ROUND_DOWN);
            System.out.println("开空偏离率:" + atrSlipRatio);*/
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
            String progressTime = barSeries.getBar(barSeries.getEndIndex()).getBeginTime().format(formatter);
            BigDecimal nowOpen = new BigDecimal(nowCandleEntry5m.getOpen());
            /*BigDecimal[] highestPriceAndAtr = getHighestPriceAndAtr(atrs, candleEntries, candleEntries.size() - 2, judgePeriod);
            BigDecimal highestPrice = highestPriceAndAtr[0];
            BigDecimal highestAtr = highestPriceAndAtr[1];
            BigDecimal initStopLossPrice = highestPrice.add(highestAtr.multiply(new BigDecimal("1")));
            BigDecimal initStopLossRate = initStopLossPrice.subtract(nowOpen).divide(nowOpen, 6, BigDecimal.ROUND_DOWN).abs();*/

            BigDecimal temp = lastAtr.multiply(new BigDecimal("1")).divide(nowOpen, 6, BigDecimal.ROUND_DOWN);
            BigDecimal initStopLossPrice = (BigDecimal.ONE.add(temp)).multiply(nowOpen);
            BigDecimal initStopLossRate = initStopLossPrice.subtract(nowOpen).divide(nowOpen, 6, BigDecimal.ROUND_DOWN).abs();
            BigDecimal limitRate = initStopLossPrice.subtract(nowOpen).divide(nowOpen, 6, BigDecimal.ROUND_DOWN).abs();
            if (initStopLossRate.compareTo(SystemParamContants.stop_loss_max) > 0) {
                return new QuantBotDetailDTO[]{quantBotDetailDTO, null};
            }

            /*BigDecimal[] lowestPriceAndAtr = getLowestPriceAndAtr(atrs, candleEntries5m, candleEntries5m.size() - 2, judgeRiseSpacePeriod);
            BigDecimal lowestPrice = lowestPriceAndAtr[0];
            BigDecimal lowestAtr = lowestPriceAndAtr[1];
            if (lowestPrice.compareTo(nowOpen.multiply(BigDecimal.ONE.subtract(initStopLossRate))) > 0) {
                return new QuantBotDetailDTO[]{quantBotDetailDTO, null};
            }*/

            BigDecimal initStopMax = (BigDecimal) redisTemplate.opsForValue().get("initStopMax:" + destinationCoins);
            List<BigDecimal> initStopMaxList = (List<BigDecimal>) redisTemplate.opsForValue().get("initStopMaxList:" + destinationCoins);
            if (initStopLossRate.compareTo(initStopMax) > 0) {
                initStopMax = initStopLossRate;
                initStopMaxList.add(initStopMax);
            }
            redisTemplate.opsForValue().set("initStopMax:" + destinationCoins, initStopMax);
            redisTemplate.opsForValue().set("initStopMaxList:" + destinationCoins, initStopMaxList);

            System.out.println(quantBotDetailDTO.getDestinationCoin() + " 空单开仓进度时间: " + progressTime + ",最大初始止损率:" + initStopMax + ",最大止损率集合:" + initStopMaxList);
            BigDecimal stopLossRate = initStopLossRate;
            BigDecimal stopWinRatio = initStopLossRate.multiply(new BigDecimal("1"));
            //BigDecimal stopWinRatio = new BigDecimal("0.005");
            BigDecimal breakEvenRate = stopWinRatio;
            //BigDecimal breakEvenRate = SystemParamContants.fee;
            //BigDecimal breakEvenRate = stopLossRate.negate();

            /*if (initStopLossRate.negate().compareTo(SystemParamContants.stop_loss_max.negate()) < 0) {
                initStopLossPrice = nowOpen.multiply(BigDecimal.ONE.add(SystemParamContants.stop_loss_max));
                stopLossRate = SystemParamContants.stop_loss_max;
            }*/

            PinBarCandlerStickDetailDTO pinBarCandlerStickDetailDTO = new PinBarCandlerStickDetailDTO();
            pinBarCandlerStickDetailDTO.setInitStopLossPrice(initStopLossPrice);
            pinBarCandlerStickDetailDTO.setStopLossPrice(initStopLossPrice);
            pinBarCandlerStickDetailDTO.setStopWinRate(stopWinRatio);
            pinBarCandlerStickDetailDTO.setBreakEvenRate(breakEvenRate);
            pinBarCandlerStickDetailDTO.setStopLossRate(stopLossRate);
            pinBarCandlerStickDetailDTO.setOpen(nowOpen.multiply(BigDecimal.ONE.subtract(slippage)));
            quantBotDetailDTO.setCurrentAddTime(String.valueOf(nowCandleEntry5m.getOpenTime()));

            //给移动止盈获取上次breakEventRate数据使用
            quantBotDetailDTO.setLastTimeRise(String.valueOf(pinBarCandlerStickDetailDTO.getBreakEvenRate()));

            quantBotDetailDTO.setPinBarCandlerStickDetailDTO(pinBarCandlerStickDetailDTO);
            return new QuantBotDetailDTO[]{quantBotDetailDTO, quantBotDetailDTO};
        } else {
            return new QuantBotDetailDTO[]{quantBotDetailDTO, null};
        }
    }


    public BarSeries getBarSeries(List<MyCandleEntry> candleEntries, Duration timePeriod) {
        // 创建一个时间序列
        BarSeries series = new BaseBarSeries();

        // 添加价格数据到时间序列
        for (MyCandleEntry myCandleEntry : candleEntries) {
            series.addBar(new BaseBar(timePeriod, ZonedDateTime.ofInstant(Instant.ofEpochMilli(myCandleEntry.getCloseTime()), ZoneId.systemDefault()),
                    PrecisionNum.valueOf(myCandleEntry.getOpen()),
                    PrecisionNum.valueOf(myCandleEntry.getHigh()),
                    PrecisionNum.valueOf(myCandleEntry.getLow()),
                    PrecisionNum.valueOf(myCandleEntry.getClose()),
                    PrecisionNum.valueOf(myCandleEntry.getVolume()),
                    PrecisionNum.valueOf(myCandleEntry.getQuoteAssetVolume()))
            );
        }

        return series;
    }

    public List<Num>[] getMACD_signal_value(BarSeries barSeries, int shortPeriod, int longPeriod, int signalPeriod) {
        MACDIndicator macdIndicator = new MACDIndicator(new ClosePriceIndicator(barSeries), shortPeriod, longPeriod);
        Indicator<Num> macdLine = macdIndicator;
        EMAIndicator signalLine = new EMAIndicator(macdLine, signalPeriod);

        List<Num> macdValues = new ArrayList<>();
        List<Num> signalValues = new ArrayList<>();
        for (int i = signalPeriod; i < barSeries.getBarCount(); i++) {
            Num macdValue = macdLine.getValue(i);
            Num signalValue = signalLine.getValue(i);

            macdValues.add(macdValue);
            signalValues.add(signalValue);
        }
        List<Num>[] results = new ArrayList[2];
        results[0] = macdValues;
        results[1] = signalValues;

        return results;
    }

    public List<Num> getATR(BarSeries barSeries, int atrPeriod) {
        // 创建 ATRIndicator 对象
        ATRIndicator atrIndicator = new ATRIndicator(barSeries, atrPeriod);

        List<Num> atrValues = new ArrayList<>();
        // 访问 ATR 指标的数值
        for (int i = atrPeriod; i < barSeries.getBarCount(); i++) {
            atrValues.add(atrIndicator.getValue(i));
        }

        return atrValues;
    }

    private static boolean isIncreasing(List<Double> data) {
        for (int i = 1; i < data.size(); i++) {
            if (data.get(i) <= data.get(i - 1)) {
                return false;
            }
        }
        return true;
    }

    private static boolean isDecreasing(List<Double> data) {
        for (int i = 1; i < data.size(); i++) {
            if (data.get(i) >= data.get(i - 1)) {
                return false;
            }
        }
        return true;
    }

    private boolean isBullEntry(List<MyCandleEntry> candleEntries, List<Num> macdValues, int signalPeriod, int judgePeriod) {
        int minMacdIndex = 0;
        BigDecimal minMacd = new BigDecimal("9999999999999999999999999999");

        for (int i = candleEntries.size() - 2; i > candleEntries.size() - 2 - judgePeriod; i--) {
            BigDecimal macd = BigDecimal.valueOf(macdValues.get(i - signalPeriod).doubleValue());
            if (macd.compareTo(minMacd) < 0) {
                minMacd = macd;
                minMacdIndex = i;
            }
        }

        int candleNum = candleEntries.size() - 1 - minMacdIndex;
        BigDecimal maxPrice = new BigDecimal("-9999999999999999999999999999");
        for (int i = minMacdIndex - 1; i > minMacdIndex - 1 - candleNum; i--) {
            BigDecimal high = BigDecimal.valueOf(candleEntries.get(i).getHigh());
            if (high.compareTo(maxPrice) > 0) {
                maxPrice = high;
            }
        }

        BigDecimal lastClose = BigDecimal.valueOf(candleEntries.get(candleEntries.size() - 2).getClose());

        return lastClose.compareTo(maxPrice) > 0;
    }

    private boolean isBearEntry(List<MyCandleEntry> candleEntries, List<Num> macdValues, int signalPeriod, int judgePeriod) {
        int maxMacdIndex = 0;
        BigDecimal maxMacd = new BigDecimal("-9999999999999999999999999999");

        for (int i = candleEntries.size() - 2; i > candleEntries.size() - 2 - judgePeriod; i--) {
            BigDecimal macd = BigDecimal.valueOf(macdValues.get(i - signalPeriod).doubleValue());
            if (macd.compareTo(maxMacd) > 0) {
                maxMacd = macd;
                maxMacdIndex = i;
            }
        }

        int candleNum = candleEntries.size() - 1 - maxMacdIndex;
        BigDecimal minPrice = new BigDecimal("9999999999999999999999999999");
        for (int i = maxMacdIndex - 1; i > maxMacdIndex - 1 - candleNum; i--) {
            BigDecimal low = BigDecimal.valueOf(candleEntries.get(i).getLow());
            if (low.compareTo(minPrice) < 0) {
                minPrice = low;
            }
        }

        BigDecimal lastClose = BigDecimal.valueOf(candleEntries.get(candleEntries.size() - 2).getClose());

        return lastClose.compareTo(minPrice) < 0;
    }

    /**
     * 计算rsi值
     *
     * @return
     */
    public BigDecimal getRsi(BarSeries barSeries, int rsiTimeFrame, int index) {
        // 创建RSI指标对象
        RSIIndicator rsiIndicator = new RSIIndicator(new ClosePriceIndicator(barSeries), rsiTimeFrame);
        // 获取RSI值
        Num rsiValue = rsiIndicator.getValue(index);
        BigDecimal value = new BigDecimal(rsiValue.doubleValue());
        return value;
    }

    // 检查十字星
    public boolean checkStar(float yesterdayClose, float yesterdayOpen,
                             float yesterdayHigh, float yesterdayLow) {
        // 计算 min(前日收盘价,前日开盘价) 和 0.01*min(前日收盘价,前日开盘价)
        float minCloseOpen = Math.min(yesterdayClose, yesterdayOpen);
        float threshold = 0.01f * minCloseOpen;

        // 判断条件
        boolean condition1 = max(yesterdayClose, yesterdayOpen) <= 1.005 * minCloseOpen;
        boolean condition2 = (yesterdayHigh - yesterdayLow) > threshold;

        // 返回满足条件的结果
        return condition1 && condition2;
    }

    // 计算 max 值
    public static double max(double a, double b) {
        return a > b ? a : b;
    }

    // 判断 MACD 是否处于底部
    public boolean isMACDBottom(double[] macdValues) {
        // 判断条件可以根据实际需求进行调整
        int bottomPeriod = 3;  // 连续多少天处于底部

        for (int i = macdValues.length - 1; i >= bottomPeriod - 1; i--) {
            boolean isBottom = true;
            for (int j = 0; j < bottomPeriod; j++) {
                if (macdValues[i - j] >= macdValues[i - j - 1]) {
                    isBottom = false;
                    break;
                }
            }
            if (isBottom) {
                return true;
            }
        }
        return false;
    }

    // 判断 MACD 是否处于顶部
    public boolean isMACDTop(double[] macdValues) {
        // 判断条件可以根据实际需求进行调整
        int topPeriod = 3;  // 连续多少天处于顶部

        for (int i = macdValues.length - 1; i >= topPeriod - 1; i--) {
            boolean isTop = true;
            for (int j = 0; j < topPeriod; j++) {
                if (macdValues[i - j] <= macdValues[i - j - 1]) {
                    isTop = false;
                    break;
                }
            }
            if (isTop) {
                return true;
            }
        }
        return false;
    }

    public Num[] getStochRsi(BarSeries series, int rsiBarCount, int stockBarCount, int kPeriod, int dPeriod, int index) {
        // 创建相对强弱指数 (RSI) 指标
        RSIIndicator rsi = new RSIIndicator(new ClosePriceIndicator(series), rsiBarCount);
        // 创建 Stochastic RSI 指标
        StochasticRSIIndicator stochRsi = new StochasticRSIIndicator(rsi, stockBarCount);
        // 计算 StochRSI K 值
        SMAIndicator stochK = new SMAIndicator(stochRsi, kPeriod);
        // 计算 StochRSI D 值
        SMAIndicator stochD = new SMAIndicator(stochK, dPeriod);
        Num StochRSI_K = stochK.getValue(index).multipliedBy(series.numOf(100));
        Num StochRSI_D = stochD.getValue(index).multipliedBy(series.numOf(100));
        Num[] stoch_values = new Num[]{StochRSI_K, StochRSI_D};
        return stoch_values;
    }

    public double getADX(BarSeries series, int diBarCount, int adxBarCount, int index) {
        ADXIndicator adxIndicator = new ADXIndicator(series, diBarCount, adxBarCount);
        double adx = adxIndicator.getValue(index).doubleValue();
        return adx;
    }

    public double getPlusDI(BarSeries series, int diBarCount, int index) {
        PlusDIIndicator plusDIIndicator = new PlusDIIndicator(series, diBarCount);
        double plusDi = plusDIIndicator.getValue(index).doubleValue();
        return plusDi;
    }

    public double getMinusDI(BarSeries series, int diBarCount, int index) {
        MinusDIIndicator minusDIIndicator = new MinusDIIndicator(series, diBarCount);
        double minusDi = minusDIIndicator.getValue(index).doubleValue();
        return minusDi;
    }

    public double getCCI(BarSeries series, int cciPeriod, int index) {
        CCIIndicator cciIndicator = new CCIIndicator(series, cciPeriod);
        double cciValue = cciIndicator.getValue(index).doubleValue();
        return cciValue;
    }

    public double getOBV(BarSeries series, int index) {
        OnBalanceVolumeIndicator onBalanceVolumeIndicator = new OnBalanceVolumeIndicator(series);
        double obvValue = onBalanceVolumeIndicator.getValue(index).doubleValue();
        return obvValue;
    }

    public SlowStochRsiResult getSlowStochRsi(BarSeries barSeries, int length, int smoothK, int smoothD, int index) {
        // 创建 ClosePriceIndicator 对象
        ClosePriceIndicator closePrice = new ClosePriceIndicator(barSeries);
        // 创建最低价和最高价指标
        LowestValueIndicator low = new LowestValueIndicator(new LowPriceIndicator(barSeries), length);
        HighestValueIndicator high = new HighestValueIndicator(new HighPriceIndicator(barSeries), length);

        BaseBarSeries rawKBarSeries = new BaseBarSeries();
        // 计算 %K
        for (int i = 0; i < barSeries.getBarCount(); i++) {
            Num rawK = closePrice.getValue(i).minus(low.getValue(i)).dividedBy(high.getValue(i).minus(low.getValue(i))).multipliedBy(barSeries.numOf(100));
            rawKBarSeries.addBar(barSeries.getBar(i).getEndTime(), rawK, rawK, rawK, rawK, rawK);
        }

        // 创建 SMAIndicator 对象
        SMAIndicator k = new SMAIndicator(new ClosePriceIndicator(rawKBarSeries), smoothK);
        // 创建 SMAIndicator 对象
        SMAIndicator d = new SMAIndicator(k, smoothD);

        return new SlowStochRsiResult(k.getValue(index), d.getValue(index));
    }

    public SupertrendResult calculateSupertrend(BarSeries series, float factor, int atrPeriod, int index) {
        Indicator<Num> highPrice = new HighPriceIndicator(series);
        Indicator<Num> lowPrice = new LowPriceIndicator(series);
        Indicator<Num> atr = new ATRIndicator(series, atrPeriod);
        // 初始化 direction，superTrend，当前 K 线的上下通道边界，前一根 K 线的上下通道边界
        Num direction = series.numOf(0);
        Num superTrend = series.numOf(0);
        Num prevSuperTrend = series.numOf(0);
        Num upperBand = null;
        Num lowerBand = null;
        Num prevUpperBand = series.numOf(0);
        Num prevLowerBand = series.numOf(0);

        int totalCount = index + 1;

        // 计算上下通道的边界和更新通道边界
        for (int i = 1; i < totalCount; i++) {
            // 计算 当前hlAvg（(High+Low)/2），也就是原脚本中的hl2
            Num hlAvg = highPrice.getValue(i).plus(lowPrice.getValue(i)).dividedBy(series.numOf(2));
            // 计算当前上下通道的边界
            upperBand = hlAvg.plus(series.numOf(factor).multipliedBy(atr.getValue(i)));
            lowerBand = hlAvg.minus(series.numOf(factor).multipliedBy(atr.getValue(i)));
            // 更新下通道边界操作，如果当前 K 线的下通道边界大于前一根 K 线的下通道边界，或者前一根 K 线的收盘价小于前一根 K 线的下通道边界，那么就将 lowerBand 的值设为当前 K 线的下通道边界；否则，将 lowerBand 的值设为前一根 K 线的下通道边界。
            lowerBand = (lowerBand.isGreaterThan(prevLowerBand) ||
                    (series.getBar(i - 1).getClosePrice().isLessThan(prevLowerBand))) ? lowerBand : prevLowerBand;
            // 更新上通道边界操作，如果当前 K 线的上通道边界小于前一根 K 线的上通道边界，或者前一根 K 线的收盘价大于前一根 K 线的上通道边界，那么就将 upperBand 的值设为当前 K 线的上通道边界；否则，将 upperBand 的值设为前一根 K 线的上通道边界。
            upperBand = (upperBand.isLessThan(prevUpperBand) ||
                    (series.getBar(i - 1).getClosePrice().isGreaterThan(prevUpperBand))) ? upperBand : prevUpperBand;
            if (prevSuperTrend.equals(prevUpperBand)) {
                direction = series.getBar(i).getClosePrice().isGreaterThan(upperBand) ? series.numOf(-1) : series.numOf(1);
            } else {
                direction = series.getBar(i).getClosePrice().isLessThan(lowerBand) ? series.numOf(1) : series.numOf(-1);
            }

            superTrend = direction.isEqual(series.numOf(-1)) ? lowerBand : upperBand;
            prevSuperTrend = superTrend;
            prevUpperBand = upperBand;
            prevLowerBand = lowerBand;
        }

        if (direction.isEqual(series.numOf(-1))) {
            direction = series.numOf(1);
        } else if (direction.isEqual(series.numOf(1))) {
            direction = series.numOf(-1);
        }

        return new SupertrendResult(superTrend, direction);
    }

    private boolean isTriangleForming(List<Double> resistancePrices, List<Double> supportPrices, List<MyCandleEntry> myCandleEntries) {
        if (resistancePrices.size() != supportPrices.size() || resistancePrices.isEmpty() || supportPrices.isEmpty()) {
            throw new IllegalArgumentException("Resistance and support prices lists must have the same non-zero length.");
        }

        // 存储相邻蜡烛的阻力位和支撑位之间的差值
        List<Double> differences = new ArrayList<>();

        int touchResistanceNum = 0;
        int touchSupportNum = 0;
        // 计算每对相邻的阻力位和支撑位之间的差值
        for (int i = 0; i < resistancePrices.size(); i++) {
            MyCandleEntry myCandleEntry = myCandleEntries.get(i);
            Double resistancePrice = resistancePrices.get(i);
            Double supportPrice = supportPrices.get(i);

            double difference = resistancePrice - supportPrice;
            differences.add(difference);

            if (Double.valueOf(myCandleEntry.getHigh()) >= resistancePrice) {
                touchResistanceNum += 1;
            }
            if (Double.valueOf(myCandleEntry.getLow()) <= supportPrice) {
                touchSupportNum += 1;
            }
        }

        // 检查差值列表是否在不断减小（或者至少不增加）
        for (int i = 1; i < differences.size(); i++) {
            if (differences.get(i) >= differences.get(i - 1)) {
                // 如果发现非递减的差值，则返回false
                return false;
            }
        }

        /*BigDecimal last = new BigDecimal(differences.get(differences.size() - 1));
        BigDecimal first = new BigDecimal(differences.get(0));
        if (last.multiply(new BigDecimal("2")).compareTo(first) >= 0) {
            return false;
        }*/
        if (touchResistanceNum < 3 || touchSupportNum < 3) {
            return false;
        }

        // 所有差值都是递减的，认为形成了三角形态
        return true;
    }

}
